Neural Network models - Leave One Participant Out CV to predict properties using 3 subwindows¶

In [1]:
import numpy as np
import pandas as pd
pd.set_option("display.max_columns", None)
pd.set_option("display.max_rows", None)
from pandas.core.common import SettingWithCopyWarning

import warnings
warnings.simplefilter(action="ignore", category=SettingWithCopyWarning)
warnings.simplefilter(action="ignore", category=UserWarning)

import random
import datetime
import time
import matplotlib.pyplot as plt
%matplotlib inline

from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import OneHotEncoder
from sklearn.model_selection import train_test_split
from sklearn.model_selection import KFold
from sklearn.metrics import f1_score
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import TensorDataset, DataLoader, ConcatDataset
import torch.optim as optim
In [2]:
# Initialise the random state
#num = random.randint(1, 500)
num = 58
torch.manual_seed(num)
np.random.seed(num)
print(f"The generated random seed is {num}") #347
The generated random seed is 58

Load data¶

3 window combined df¶

In [3]:
path = "/Users/niharawarawita/Desktop/MSc Project/Data and code/complete_dataset_3subwindows.csv"
df = pd.read_csv(path)
df.head(10)
Out[3]:
participant_id clothes_id property_id property_name interaction_id rating rating_level rating_level_num sub_window_num subwindow_start_time subwindow_end_time max_ch1_Hand0 max_ch2_Hand0 max_ch3_Hand0 max_ch4_Hand0 max_ch5_Hand0 max_ch6_Hand0 max_ch7_Hand0 max_ch8_Hand0 mean_ch1_Hand0 mean_ch2_Hand0 mean_ch3_Hand0 mean_ch4_Hand0 mean_ch5_Hand0 mean_ch6_Hand0 mean_ch7_Hand0 mean_ch8_Hand0 std_ch1_Hand0 std_ch2_Hand0 std_ch3_Hand0 std_ch4_Hand0 std_ch5_Hand0 std_ch6_Hand0 std_ch7_Hand0 std_ch8_Hand0 max_ch1_Hand1 max_ch2_Hand1 max_ch3_Hand1 max_ch4_Hand1 max_ch5_Hand1 max_ch6_Hand1 max_ch7_Hand1 max_ch8_Hand1 mean_ch1_Hand1 mean_ch2_Hand1 mean_ch3_Hand1 mean_ch4_Hand1 mean_ch5_Hand1 mean_ch6_Hand1 mean_ch7_Hand1 mean_ch8_Hand1 std_ch1_Hand1 std_ch2_Hand1 std_ch3_Hand1 std_ch4_Hand1 std_ch5_Hand1 std_ch6_Hand1 std_ch7_Hand1 std_ch8_Hand1 max_Ax_Hand0 max_Ay_Hand0 max_Az_Hand0 max_Vx_Hand0 max_Vy_Hand0 max_Vz_Hand0 max_Jx_Hand0 max_Jy_Hand0 max_Jz_Hand0 mean_Ax_Hand0 mean_Ay_Hand0 mean_Az_Hand0 mean_Vx_Hand0 mean_Vy_Hand0 mean_Vz_Hand0 mean_Jx_Hand0 mean_Jy_Hand0 mean_Jz_Hand0 std_Ax_Hand0 std_Ay_Hand0 std_Az_Hand0 std_Vx_Hand0 std_Vy_Hand0 std_Vz_Hand0 std_Jx_Hand0 std_Jy_Hand0 std_Jz_Hand0 max_Ax_Hand1 max_Ay_Hand1 max_Az_Hand1 max_Vx_Hand1 max_Vy_Hand1 max_Vz_Hand1 max_Jx_Hand1 max_Jy_Hand1 max_Jz_Hand1 mean_Ax_Hand1 mean_Ay_Hand1 mean_Az_Hand1 mean_Vx_Hand1 mean_Vy_Hand1 mean_Vz_Hand1 mean_Jx_Hand1 mean_Jy_Hand1 mean_Jz_Hand1 std_Ax_Hand1 std_Ay_Hand1 std_Az_Hand1 std_Vx_Hand1 std_Vy_Hand1 std_Vz_Hand1 std_Jx_Hand1 std_Jy_Hand1 std_Jz_Hand1 max_w_Hand0 max_x_Hand0 max_y_Hand0 max_z_Hand0 max_AVx_Hand0 max_AVy_Hand0 max_AVz_Hand0 max_AAx_Hand0 max_AAy_Hand0 max_AAz_Hand0 max_AJx_Hand0 max_AJy_Hand0 max_AJz_Hand0 mean_w_Hand0 mean_x_Hand0 mean_y_Hand0 mean_z_Hand0 mean_AVx_Hand0 mean_AVy_Hand0 mean_AVz_Hand0 mean_AAx_Hand0 mean_AAy_Hand0 mean_AAz_Hand0 mean_AJx_Hand0 mean_AJy_Hand0 mean_AJz_Hand0 std_w_Hand0 std_x_Hand0 std_y_Hand0 std_z_Hand0 std_AVx_Hand0 std_AVy_Hand0 std_AVz_Hand0 std_AAx_Hand0 std_AAy_Hand0 std_AAz_Hand0 std_AJx_Hand0 std_AJy_Hand0 std_AJz_Hand0 max_w_Hand1 max_x_Hand1 max_y_Hand1 max_z_Hand1 max_AVx_Hand1 max_AVy_Hand1 max_AVz_Hand1 max_AAx_Hand1 max_AAy_Hand1 max_AAz_Hand1 max_AJx_Hand1 max_AJy_Hand1 max_AJz_Hand1 mean_w_Hand1 mean_x_Hand1 mean_y_Hand1 mean_z_Hand1 mean_AVx_Hand1 mean_AVy_Hand1 mean_AVz_Hand1 mean_AAx_Hand1 mean_AAy_Hand1 mean_AAz_Hand1 mean_AJx_Hand1 mean_AJy_Hand1 mean_AJz_Hand1 std_w_Hand1 std_x_Hand1 std_y_Hand1 std_z_Hand1 std_AVx_Hand1 std_AVy_Hand1 std_AVz_Hand1 std_AAx_Hand1 std_AAy_Hand1 std_AAz_Hand1 std_AJx_Hand1 std_AJy_Hand1 std_AJz_Hand1
0 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.481 2021-08-05 13:21:32.468 0.504132 0.620513 0.675978 0.500000 0.759036 0.652406 0.76250 0.666667 0.497498 0.612780 0.665895 0.492285 0.718526 0.636907 0.748853 0.660720 0.002329 0.002760 0.003011 0.002201 0.006194 0.004289 0.003634 0.002595 0.508197 0.929578 0.757225 0.730159 0.497959 0.995918 0.663366 0.580645 0.497102 0.848495 0.692072 0.634859 0.491574 0.511567 0.596728 0.558018 0.003056 0.009851 0.011220 0.016046 0.002283 0.125342 0.014496 0.005100 -0.850708 -0.068771 0.490311 0.000525 0.000406 0.000903 1.269531 1.220703 2.258301 -0.863979 -0.089162 0.468123 -4.589844e-06 1.483398e-05 -1.191406e-05 -0.010928 -0.052313 0.060087 0.006994 0.008424 0.010178 0.000201 0.000180 0.000270 0.599364 0.630856 0.794158 1.023270 0.042786 -0.178879 0.001218 0.001529 0.001429 4.089355 5.468750 3.271484 0.970242 -0.011443 -0.239064 -3.020508e-05 -8.115234e-06 0.000065 0.061211 0.036287 -0.170119 0.017187 0.014988 0.034359 0.000440 0.000417 0.000641 1.262790 1.374306 1.977670 0.179352 0.488418 0.160615 -0.840857 0.133141 0.061469 0.117029 4.332320 2.887801 19.812834 554.574503 316.450316 1338.775861 0.171550 0.486515 0.155002 -0.842509 -0.002358 -0.006487 -0.037808 -0.069210 0.040128 0.213198 -18.896953 -5.997847 29.264918 0.004033 0.001122 0.003172 0.000812 0.034035 0.027288 0.100030 1.808784 1.349269 6.515867 214.502864 135.316892 572.754308 0.618680 -0.175326 -0.753378 -0.128901 0.215491 0.583907 0.275227 21.603607 56.450019 29.424453 2797.763022 9050.317251 2366.953044 0.602964 -0.177295 -0.766545 -0.131596 -0.011132 -0.035192 -0.000290 -0.692534 -0.994509 -0.440578 19.388504 94.341574 -56.539654 0.007223 0.001357 0.006089 0.001773 0.140168 0.419609 0.109731 8.409602 20.970763 7.985693 769.853603 1878.284384 898.072858
1 7 14 3 smoothness 1 3 medium 2 2 2021-08-05 13:21:32.495 2021-08-05 13:21:33.464 0.504132 0.620513 0.675978 0.500000 0.759036 0.663102 0.75625 0.666667 0.497417 0.612789 0.666077 0.492186 0.718908 0.637194 0.748828 0.660428 0.002321 0.002785 0.002810 0.002245 0.006368 0.004426 0.002994 0.002613 0.508197 0.957746 0.809249 0.746032 0.497959 0.995918 0.683168 0.585254 0.496918 0.848890 0.692686 0.634612 0.491212 0.492734 0.596994 0.558059 0.003603 0.012522 0.017839 0.015241 0.002220 0.168270 0.014712 0.007247 -0.846313 -0.069260 0.488846 0.000545 0.000305 0.000813 2.929688 1.190186 3.580729 -0.863563 -0.084855 0.464930 -6.825973e-06 2.042809e-06 -2.849968e-06 0.048335 -0.042143 0.040023 0.006822 0.005053 0.009881 0.000240 0.000117 0.000297 0.712536 0.499915 0.939672 0.999344 0.062317 -0.159836 0.001187 0.001328 0.001074 3.255208 3.320312 4.882812 0.965975 -0.000925 -0.259182 3.190430e-05 6.406250e-05 -0.000024 -0.095776 -0.165980 0.144850 0.015653 0.019206 0.046904 0.000333 0.000457 0.000460 1.187168 1.426576 1.346959 0.164387 0.492346 0.149139 -0.843806 0.051026 0.074743 0.071737 8.423988 6.857490 10.689540 2084.369900 445.379626 810.506826 0.160231 0.490322 0.145928 -0.844157 -0.003892 -0.003804 -0.018201 -0.036467 0.077885 -0.006631 26.988689 -7.739067 -51.168052 0.002767 0.001331 0.002246 0.000222 0.031651 0.021172 0.067094 1.891410 1.482885 4.074346 324.990077 135.612823 500.564267 0.618863 -0.150822 -0.754349 -0.114060 0.383834 0.784153 0.553013 11.380460 29.010612 33.358820 2752.365093 6546.331906 2181.850987 0.596188 -0.163353 -0.775710 -0.124714 0.021907 0.013755 0.012748 -1.111580 -0.334962 0.021466 -90.668628 -64.601575 35.073660 0.015482 0.009833 0.014861 0.007212 0.166403 0.417988 0.173217 7.359519 14.858287 9.153837 744.182656 1454.186126 769.701026
2 7 14 3 smoothness 1 3 medium 2 3 2021-08-05 13:21:33.513 2021-08-05 13:21:46.475 0.685950 0.728205 0.849162 0.607438 0.777108 0.700535 0.87500 0.733333 0.497469 0.612832 0.666206 0.492255 0.718535 0.637126 0.748788 0.660685 0.011144 0.006879 0.009090 0.007845 0.005614 0.004051 0.005506 0.004440 0.516393 0.936620 0.832370 0.751323 0.995918 0.995918 0.698020 0.622120 0.496948 0.848779 0.691786 0.634099 0.486646 0.498963 0.595900 0.557786 0.003032 0.007777 0.009667 0.009077 0.043924 0.108942 0.010389 0.006009 -0.713501 0.048904 0.572830 0.006123 0.002393 0.002616 15.869141 6.692325 6.749770 -0.868275 -0.069352 0.459729 -2.960650e-05 -6.790516e-07 -3.816164e-06 0.042151 0.006334 -0.003044 0.024366 0.017504 0.021913 0.000905 0.000376 0.000411 1.608533 0.921114 1.017115 1.060379 0.134583 -0.014328 0.001955 0.002280 0.005502 11.568510 13.627486 7.359096 0.978988 -0.000388 -0.202378 4.738978e-06 2.112100e-07 -0.000013 -0.005919 -0.001242 0.023884 0.015082 0.015613 0.041390 0.000334 0.000404 0.000483 1.085616 1.194701 1.336285 0.168521 0.505227 0.142912 -0.835808 0.316624 0.593621 0.331014 19.806659 22.033338 26.051293 2206.180328 2613.281789 2713.864594 0.155634 0.496838 0.135235 -0.842923 -0.001639 -0.004225 0.000291 -0.003520 -0.114047 0.050148 1.585695 -0.670795 3.401131 0.005331 0.007307 0.004144 0.004806 0.054181 0.088889 0.070436 2.939673 3.487398 4.355037 268.202026 277.300592 448.167800 0.647831 -0.136257 -0.732800 -0.102524 0.879971 1.989502 1.122907 49.389847 85.475258 61.100255 4256.775521 8723.328584 4294.956003 0.619735 -0.153120 -0.759202 -0.124798 0.001542 0.004674 -0.003122 0.079193 0.174868 0.141086 4.852312 18.350814 2.436863 0.012631 0.008083 0.012225 0.012151 0.123687 0.282669 0.113030 4.806996 10.779876 6.534156 486.415887 1142.095742 625.153662
3 7 14 4 thickness 2 5 medium 2 1 2021-08-05 13:22:02.060 2021-08-05 13:22:03.029 0.512397 0.661538 0.754190 0.512397 0.759036 0.673797 0.76250 0.677778 0.497326 0.612893 0.666100 0.484996 0.718373 0.637000 0.748664 0.660854 0.004125 0.014409 0.021173 0.058099 0.007076 0.005177 0.005281 0.004803 0.516393 0.873239 0.716763 0.666667 0.493878 0.497959 0.643564 0.580645 0.496862 0.848702 0.691813 0.634084 0.491064 0.493647 0.593827 0.557622 0.003913 0.006136 0.005968 0.004635 0.002087 0.001368 0.008473 0.005300 -0.724731 0.207108 0.604568 0.001240 0.002000 0.000923 6.787109 3.352865 2.838135 -0.789386 0.166772 0.569221 -1.656327e-05 5.648744e-06 6.577436e-06 0.128443 -0.119382 0.047230 0.021868 0.015788 0.017773 0.000546 0.000486 0.000461 1.863614 1.430691 1.313220 1.033524 0.126770 0.421707 0.001523 0.000680 0.001583 5.789621 3.756010 5.208333 0.939998 0.078811 0.345779 -5.450195e-05 -9.718750e-05 -0.000015 0.111309 0.174966 -0.011341 0.032360 0.014418 0.032139 0.000701 0.000572 0.000436 1.909429 1.065716 1.424733 0.211566 0.465286 0.013511 -0.859402 0.093546 0.263660 0.136374 10.712655 24.969117 24.077240 2666.816885 1920.723426 5029.040161 0.205977 0.460094 0.012212 -0.863552 0.000240 0.012612 -0.032937 0.277966 0.539358 -0.114937 39.024051 -14.919398 87.718777 0.002371 0.002726 0.000789 0.001891 0.062111 0.086016 0.096223 3.429911 6.023802 6.526026 441.445219 477.288587 875.383706 0.733975 -0.215858 -0.515914 -0.370804 0.271520 0.413471 0.793342 29.883033 33.672845 86.168465 3965.979471 4675.769180 11733.432855 0.726422 -0.222149 -0.527491 -0.380252 -0.081652 -0.042828 0.027246 -1.330705 -1.340691 1.024436 -49.463745 -93.159203 -58.539333 0.005213 0.004116 0.008078 0.003958 0.198462 0.183171 0.155875 11.152448 9.963270 16.088213 1150.663729 1135.642103 2119.655762
4 7 14 4 thickness 2 5 medium 2 2 2021-08-05 13:22:03.061 2021-08-05 13:22:04.047 0.504132 0.635897 0.737430 1.000000 0.746988 0.652406 0.76250 0.672222 0.497305 0.612760 0.666103 0.539813 0.720609 0.636990 0.748779 0.661079 0.003440 0.007323 0.011248 0.095872 0.007634 0.003822 0.004761 0.004264 0.512295 0.866197 0.710983 0.650794 0.497959 0.497959 0.722772 0.599078 0.496943 0.848932 0.691707 0.633865 0.491129 0.493722 0.594159 0.558040 0.003295 0.004746 0.003927 0.004114 0.002148 0.001221 0.017247 0.007301 -0.774048 0.188553 0.582108 0.000586 0.000533 0.000714 2.859933 1.497396 2.392578 -0.796210 0.169789 0.556567 -1.621293e-05 1.522640e-05 -6.975446e-08 0.037976 -0.004908 0.032503 0.010191 0.008518 0.010531 0.000297 0.000196 0.000290 0.819147 0.545627 0.845935 1.021317 0.099915 0.340652 0.002075 0.001179 0.000612 3.200955 1.819957 1.864347 0.956346 0.070920 0.300213 4.262695e-05 9.736328e-06 -0.000034 -0.036841 -0.036219 0.075440 0.021201 0.012754 0.029698 0.000486 0.000285 0.000374 1.348408 0.832293 0.830523 0.202624 0.467448 0.012214 -0.860776 0.052285 0.040986 0.116178 2.856049 3.770583 15.126930 312.982165 281.025841 1062.566337 0.200699 0.466227 0.007997 -0.861557 -0.006016 -0.012182 -0.007998 0.021963 0.064504 0.191972 7.439429 3.549816 8.698628 0.001243 0.001357 0.001932 0.000563 0.026385 0.029268 0.078408 1.107083 1.317382 4.622568 85.712120 106.001201 406.024850 0.722931 -0.229336 -0.534479 -0.366098 0.563110 0.565189 0.085749 12.485845 20.251992 7.395605 1233.738922 2111.723609 964.527774 0.715442 -0.232278 -0.544587 -0.370770 0.045293 0.053730 -0.001529 -0.013939 0.110153 -0.246766 -31.768089 -36.879092 -7.538979 0.006682 0.002770 0.009360 0.002573 0.181719 0.217952 0.053026 5.253641 7.297097 3.331552 548.393076 819.998059 375.285448
5 7 14 4 thickness 2 5 medium 2 3 2021-08-05 13:22:04.089 2021-08-05 13:22:17.056 0.553719 0.702564 0.798883 1.000000 0.843374 0.754011 0.85625 0.838889 0.497505 0.613086 0.666296 0.504482 0.719296 0.637041 0.748460 0.661134 0.005483 0.014608 0.021523 0.086024 0.013988 0.011014 0.010647 0.012910 0.516393 0.908451 0.757225 1.000000 0.506122 0.995918 0.737624 0.631336 0.496977 0.848712 0.691639 0.634160 0.491135 0.498371 0.594707 0.557902 0.003472 0.006247 0.005734 0.009682 0.002139 0.072799 0.016020 0.008990 -0.495728 0.442459 0.703690 0.005518 0.006189 0.002979 15.733507 11.596680 9.277344 -0.758163 0.214571 0.594610 9.725811e-06 -4.071514e-07 -8.804087e-07 -0.007886 -0.011941 0.011571 0.040677 0.046681 0.028793 0.000964 0.000991 0.000583 2.786852 2.859017 1.729196 1.025223 0.165344 0.481277 0.005273 0.002097 0.005072 11.779785 7.742746 4.296875 0.930939 0.045716 0.377158 1.475377e-06 7.309924e-06 0.000006 -0.022335 -0.028634 -0.001207 0.024952 0.021866 0.034461 0.000633 0.000371 0.000427 1.557721 1.131095 1.057328 0.304236 0.469451 0.041448 -0.850884 0.835660 0.523349 0.701497 47.757157 29.508942 99.417330 3720.608701 3339.189714 12240.574053 0.201429 0.444563 -0.022133 -0.871543 -0.006513 0.000234 -0.012988 -0.050343 -0.140312 0.216882 0.530592 -3.321829 32.290963 0.032100 0.010512 0.022419 0.008509 0.135674 0.107296 0.181583 6.942452 5.329504 9.024727 633.454890 467.112285 938.088172 0.755172 -0.198675 -0.489715 -0.348140 0.645748 0.659454 0.690995 33.174078 30.444952 23.711127 4015.796847 2850.002331 3281.919685 0.740970 -0.226013 -0.510855 -0.372205 0.003137 0.006422 0.000006 0.087152 0.043305 0.032090 -4.054701 -1.942459 2.477150 0.008967 0.007630 0.014624 0.004419 0.136329 0.136392 0.080490 5.948223 5.273546 4.484067 548.302677 461.158083 430.242493
6 7 14 5 warmth 3 4 medium 2 1 2021-08-05 13:22:31.916 2021-08-05 13:22:32.885 0.541322 0.635897 0.737430 1.000000 0.969880 0.754011 0.90000 0.711111 0.497367 0.613213 0.666133 0.531258 0.720450 0.637356 0.748576 0.661156 0.008533 0.007315 0.014736 0.137396 0.020352 0.014732 0.025558 0.008438 0.504098 0.859155 0.699422 0.645503 0.493878 0.591837 0.633663 0.571429 0.496926 0.848481 0.691474 0.634001 0.491215 0.494173 0.594639 0.557757 0.002602 0.004765 0.003895 0.004512 0.002198 0.022021 0.009568 0.003340 -0.630493 0.292557 0.725662 0.001993 0.001768 0.002492 14.439174 4.418945 6.011963 -0.754536 0.110555 0.615984 -1.627930e-05 -1.258984e-04 4.658203e-05 0.367935 -0.548133 0.157648 0.053432 0.106904 0.055757 0.000789 0.000949 0.000699 2.943439 3.500887 1.754305 0.990555 -0.065125 0.314285 0.000483 0.000718 0.001211 4.123264 3.662109 1.464844 0.959209 -0.098711 0.290963 1.596009e-05 -2.948836e-05 0.000020 0.070368 0.034191 -0.107028 0.012857 0.009945 0.013171 0.000245 0.000285 0.000335 0.961570 0.911666 0.941243 0.200454 0.461937 0.110280 -0.866305 1.129284 1.729592 3.032375 55.003635 56.696369 203.242726 4136.161069 4946.896019 15228.395256 0.189911 0.430333 0.024649 -0.880448 0.229305 0.227613 0.147295 0.223691 0.297201 0.580471 -87.960280 -106.613553 -240.938226 0.004193 0.029433 0.044366 0.012622 0.292127 0.402421 0.602283 13.551026 16.513205 40.830863 1344.718745 1649.489996 3942.378448 0.806178 -0.075378 -0.584129 -0.022996 0.074675 0.221001 0.131363 9.875660 10.772344 33.755006 1151.414467 923.423614 4828.801803 0.803182 -0.083425 -0.589053 -0.030118 -0.011975 0.014500 -0.057538 0.409021 -0.526483 0.035310 20.598778 -33.044542 53.587612 0.002457 0.004266 0.003681 0.003448 0.039194 0.114553 0.133050 2.240763 4.172808 10.907450 282.637410 364.125511 1378.104484
7 7 14 5 warmth 3 4 medium 2 2 2021-08-05 13:22:32.921 2021-08-05 13:22:33.908 0.516529 0.630769 0.715084 1.000000 0.771084 0.743316 1.00000 0.716667 0.497377 0.612720 0.666026 0.534026 0.720280 0.637084 0.749341 0.660992 0.004428 0.004363 0.008239 0.138922 0.010592 0.015469 0.032984 0.008952 0.504098 0.859155 0.699422 0.645503 0.493878 0.669388 0.648515 0.571429 0.496918 0.848688 0.691666 0.633888 0.491040 0.494061 0.594707 0.557829 0.002429 0.004383 0.003645 0.003689 0.001949 0.018184 0.007479 0.002981 -0.637817 0.085037 0.705154 0.002688 0.002539 0.001668 11.946615 10.742188 7.136418 -0.769683 -0.069289 0.609881 -1.024707e-04 -3.987305e-05 -1.062695e-04 0.130856 0.195704 0.049857 0.056362 0.051264 0.048677 0.001089 0.001192 0.000845 2.922376 3.486885 1.934238 0.982742 -0.081726 0.315750 0.000574 0.000500 0.000831 1.953125 0.773112 1.403809 0.957391 -0.094119 0.293777 -5.244141e-06 1.746094e-05 0.000016 -0.027315 -0.020972 -0.085668 0.010017 0.007187 0.013378 0.000202 0.000157 0.000260 0.600097 0.424049 0.679792 0.193081 0.444410 0.110763 -0.883228 0.953516 0.497843 0.562688 28.047074 51.438817 114.042184 2597.360965 2336.045220 7348.000102 0.124725 0.426547 0.096821 -0.889832 0.069070 -0.070847 -0.221369 -0.594438 0.253096 -1.259279 3.884025 6.008674 -192.191792 0.032551 0.015930 0.005492 0.003001 0.216621 0.220669 0.588492 10.986433 10.986367 37.223549 802.466304 787.945613 3647.366979 0.807773 -0.087211 -0.581572 -0.033545 0.060515 0.082924 0.187794 3.049213 6.575058 27.655334 219.198164 994.299267 2347.720525 0.802627 -0.089810 -0.588138 -0.041941 0.008288 -0.030010 -0.051537 0.013590 -0.043794 -1.045436 -0.286329 12.855497 2.286077 0.003499 0.001669 0.004241 0.005111 0.019737 0.067714 0.148505 0.890300 2.983282 9.940538 74.094374 227.550948 905.421557
8 7 14 5 warmth 3 4 medium 2 3 2021-08-05 13:22:33.943 2021-08-05 13:22:46.901 0.504132 0.620513 0.675978 1.000000 0.753012 0.652406 0.75625 0.666667 0.497555 0.612646 0.666111 0.497455 0.718864 0.636978 0.748824 0.660607 0.002255 0.002709 0.002836 0.046534 0.004099 0.002556 0.002994 0.002366 0.577869 0.915493 0.809249 0.682540 0.995918 0.873469 0.702970 0.608295 0.496914 0.848668 0.691479 0.634025 0.492229 0.494331 0.594055 0.557547 0.004907 0.006326 0.007682 0.004640 0.056979 0.026719 0.005584 0.003448 -0.755981 -0.051682 0.629959 0.000739 0.001374 0.002246 3.255208 1.613451 2.502441 -0.779094 -0.071283 0.602464 9.041622e-07 5.968817e-07 4.584793e-06 0.001733 0.002841 -0.010751 0.009569 0.010464 0.012897 0.000194 0.000207 0.000319 0.484825 0.448576 0.656571 1.187332 0.063293 0.467117 0.004705 0.002386 0.002492 14.160156 3.987630 5.696615 0.937241 -0.087875 0.348135 -2.234507e-07 1.086783e-05 0.000003 -0.004640 -0.028797 0.015028 0.032818 0.022120 0.074620 0.000564 0.000321 0.000398 1.498355 0.947497 1.130527 0.089504 0.451663 0.094064 -0.885182 0.099985 0.814414 1.598763 6.557470 32.573741 52.519227 1119.885376 2756.053488 19593.461070 0.008720 0.438694 0.043271 -0.896928 -0.002236 0.002943 -0.027811 0.007343 -0.030974 0.190422 1.059380 -5.961497 23.492949 0.027758 0.004081 0.017903 0.003679 0.018631 0.056792 0.189555 0.854680 2.428383 7.714206 99.617406 313.443456 1196.663038 0.836393 -0.054847 -0.520393 -0.037838 0.366688 1.493906 1.229068 32.989582 46.509508 73.605495 2836.091259 5228.533317 7778.819167 0.814328 -0.118854 -0.557526 -0.096314 0.002662 0.002451 -0.016987 -0.041973 -0.008146 -0.305426 -1.126181 -0.480905 -24.261460 0.020973 0.017974 0.032082 0.029029 0.082006 0.267581 0.192136 3.198438 7.364610 9.584111 272.472840 618.347885 1022.027358
9 7 14 6 flexibility 4 1 low 1 1 2021-08-05 13:23:00.627 2021-08-05 13:23:01.621 0.553719 0.907692 0.938548 1.000000 0.939759 0.711230 0.90000 0.738889 0.497474 0.613952 0.666267 0.534995 0.722797 0.637314 0.748474 0.661274 0.016284 0.048497 0.051068 0.175105 0.034314 0.016219 0.018106 0.013654 0.540984 0.908451 0.739884 0.793651 0.497959 0.502041 0.717822 0.640553 0.497050 0.849685 0.692418 0.634612 0.491286 0.493680 0.594688 0.558375 0.010524 0.013761 0.010472 0.019357 0.002313 0.001949 0.033387 0.025487 -0.488403 0.399979 0.732986 0.003457 0.004404 0.001719 15.364583 20.080566 6.901042 -0.688021 0.251760 0.659535 -7.075096e-06 5.670041e-05 -1.309690e-04 0.120762 0.125691 0.153056 0.066806 0.069523 0.033788 0.001710 0.001847 0.001188 5.289589 5.222964 2.715770 1.098953 0.191711 0.534500 0.003911 0.002941 0.002891 17.382812 5.106608 4.699707 0.893211 0.133313 0.439354 -3.621094e-05 3.176758e-05 0.000003 0.094182 -0.240880 0.014179 0.055625 0.034602 0.029598 0.001629 0.000933 0.000620 4.491664 2.375156 1.628285 0.249743 0.415037 -0.027648 -0.875806 0.711375 0.732153 0.678705 42.333498 34.676926 76.460467 4649.299799 2602.846516 4253.812596 0.235366 0.408364 -0.037423 -0.881097 0.002172 0.054805 -0.062035 0.257850 -1.318093 1.169602 -102.321084 -203.355012 156.283713 0.007431 0.004227 0.005104 0.003611 0.332137 0.247243 0.442337 20.231500 16.003703 26.441457 2492.189579 1717.330405 2120.953184 0.713223 -0.215995 -0.467366 -0.461506 0.488642 0.306945 0.288757 20.761490 23.849124 15.865774 4599.641047 2866.425848 1105.649570 0.707679 -0.222934 -0.479116 -0.468872 -0.009047 0.038615 -0.022886 -0.266041 0.622298 -0.175560 31.471239 18.820004 -18.120447 0.003362 0.003920 0.007105 0.004806 0.231302 0.168814 0.119388 9.319012 8.356834 6.251922 907.661263 745.336220 543.331560
In [4]:
# Remove enjoyment as we are only considering physical properties
print(df.shape)
physical_df = df[df.property_name!='enjoyment']
physical_df.shape
(1512, 191)
Out[4]:
(1260, 191)
In [5]:
# Obtain a df of features
features_df = physical_df.iloc[:,11:]
features_df.head()
Out[5]:
max_ch1_Hand0 max_ch2_Hand0 max_ch3_Hand0 max_ch4_Hand0 max_ch5_Hand0 max_ch6_Hand0 max_ch7_Hand0 max_ch8_Hand0 mean_ch1_Hand0 mean_ch2_Hand0 mean_ch3_Hand0 mean_ch4_Hand0 mean_ch5_Hand0 mean_ch6_Hand0 mean_ch7_Hand0 mean_ch8_Hand0 std_ch1_Hand0 std_ch2_Hand0 std_ch3_Hand0 std_ch4_Hand0 std_ch5_Hand0 std_ch6_Hand0 std_ch7_Hand0 std_ch8_Hand0 max_ch1_Hand1 max_ch2_Hand1 max_ch3_Hand1 max_ch4_Hand1 max_ch5_Hand1 max_ch6_Hand1 max_ch7_Hand1 max_ch8_Hand1 mean_ch1_Hand1 mean_ch2_Hand1 mean_ch3_Hand1 mean_ch4_Hand1 mean_ch5_Hand1 mean_ch6_Hand1 mean_ch7_Hand1 mean_ch8_Hand1 std_ch1_Hand1 std_ch2_Hand1 std_ch3_Hand1 std_ch4_Hand1 std_ch5_Hand1 std_ch6_Hand1 std_ch7_Hand1 std_ch8_Hand1 max_Ax_Hand0 max_Ay_Hand0 max_Az_Hand0 max_Vx_Hand0 max_Vy_Hand0 max_Vz_Hand0 max_Jx_Hand0 max_Jy_Hand0 max_Jz_Hand0 mean_Ax_Hand0 mean_Ay_Hand0 mean_Az_Hand0 mean_Vx_Hand0 mean_Vy_Hand0 mean_Vz_Hand0 mean_Jx_Hand0 mean_Jy_Hand0 mean_Jz_Hand0 std_Ax_Hand0 std_Ay_Hand0 std_Az_Hand0 std_Vx_Hand0 std_Vy_Hand0 std_Vz_Hand0 std_Jx_Hand0 std_Jy_Hand0 std_Jz_Hand0 max_Ax_Hand1 max_Ay_Hand1 max_Az_Hand1 max_Vx_Hand1 max_Vy_Hand1 max_Vz_Hand1 max_Jx_Hand1 max_Jy_Hand1 max_Jz_Hand1 mean_Ax_Hand1 mean_Ay_Hand1 mean_Az_Hand1 mean_Vx_Hand1 mean_Vy_Hand1 mean_Vz_Hand1 mean_Jx_Hand1 mean_Jy_Hand1 mean_Jz_Hand1 std_Ax_Hand1 std_Ay_Hand1 std_Az_Hand1 std_Vx_Hand1 std_Vy_Hand1 std_Vz_Hand1 std_Jx_Hand1 std_Jy_Hand1 std_Jz_Hand1 max_w_Hand0 max_x_Hand0 max_y_Hand0 max_z_Hand0 max_AVx_Hand0 max_AVy_Hand0 max_AVz_Hand0 max_AAx_Hand0 max_AAy_Hand0 max_AAz_Hand0 max_AJx_Hand0 max_AJy_Hand0 max_AJz_Hand0 mean_w_Hand0 mean_x_Hand0 mean_y_Hand0 mean_z_Hand0 mean_AVx_Hand0 mean_AVy_Hand0 mean_AVz_Hand0 mean_AAx_Hand0 mean_AAy_Hand0 mean_AAz_Hand0 mean_AJx_Hand0 mean_AJy_Hand0 mean_AJz_Hand0 std_w_Hand0 std_x_Hand0 std_y_Hand0 std_z_Hand0 std_AVx_Hand0 std_AVy_Hand0 std_AVz_Hand0 std_AAx_Hand0 std_AAy_Hand0 std_AAz_Hand0 std_AJx_Hand0 std_AJy_Hand0 std_AJz_Hand0 max_w_Hand1 max_x_Hand1 max_y_Hand1 max_z_Hand1 max_AVx_Hand1 max_AVy_Hand1 max_AVz_Hand1 max_AAx_Hand1 max_AAy_Hand1 max_AAz_Hand1 max_AJx_Hand1 max_AJy_Hand1 max_AJz_Hand1 mean_w_Hand1 mean_x_Hand1 mean_y_Hand1 mean_z_Hand1 mean_AVx_Hand1 mean_AVy_Hand1 mean_AVz_Hand1 mean_AAx_Hand1 mean_AAy_Hand1 mean_AAz_Hand1 mean_AJx_Hand1 mean_AJy_Hand1 mean_AJz_Hand1 std_w_Hand1 std_x_Hand1 std_y_Hand1 std_z_Hand1 std_AVx_Hand1 std_AVy_Hand1 std_AVz_Hand1 std_AAx_Hand1 std_AAy_Hand1 std_AAz_Hand1 std_AJx_Hand1 std_AJy_Hand1 std_AJz_Hand1
0 0.504132 0.620513 0.675978 0.500000 0.759036 0.652406 0.76250 0.666667 0.497498 0.612780 0.665895 0.492285 0.718526 0.636907 0.748853 0.660720 0.002329 0.002760 0.003011 0.002201 0.006194 0.004289 0.003634 0.002595 0.508197 0.929578 0.757225 0.730159 0.497959 0.995918 0.663366 0.580645 0.497102 0.848495 0.692072 0.634859 0.491574 0.511567 0.596728 0.558018 0.003056 0.009851 0.011220 0.016046 0.002283 0.125342 0.014496 0.005100 -0.850708 -0.068771 0.490311 0.000525 0.000406 0.000903 1.269531 1.220703 2.258301 -0.863979 -0.089162 0.468123 -0.000005 1.483398e-05 -1.191406e-05 -0.010928 -0.052313 0.060087 0.006994 0.008424 0.010178 0.000201 0.000180 0.000270 0.599364 0.630856 0.794158 1.023270 0.042786 -0.178879 0.001218 0.001529 0.001429 4.089355 5.468750 3.271484 0.970242 -0.011443 -0.239064 -0.000030 -8.115234e-06 0.000065 0.061211 0.036287 -0.170119 0.017187 0.014988 0.034359 0.000440 0.000417 0.000641 1.262790 1.374306 1.977670 0.179352 0.488418 0.160615 -0.840857 0.133141 0.061469 0.117029 4.332320 2.887801 19.812834 554.574503 316.450316 1338.775861 0.171550 0.486515 0.155002 -0.842509 -0.002358 -0.006487 -0.037808 -0.069210 0.040128 0.213198 -18.896953 -5.997847 29.264918 0.004033 0.001122 0.003172 0.000812 0.034035 0.027288 0.100030 1.808784 1.349269 6.515867 214.502864 135.316892 572.754308 0.618680 -0.175326 -0.753378 -0.128901 0.215491 0.583907 0.275227 21.603607 56.450019 29.424453 2797.763022 9050.317251 2366.953044 0.602964 -0.177295 -0.766545 -0.131596 -0.011132 -0.035192 -0.000290 -0.692534 -0.994509 -0.440578 19.388504 94.341574 -56.539654 0.007223 0.001357 0.006089 0.001773 0.140168 0.419609 0.109731 8.409602 20.970763 7.985693 769.853603 1878.284384 898.072858
1 0.504132 0.620513 0.675978 0.500000 0.759036 0.663102 0.75625 0.666667 0.497417 0.612789 0.666077 0.492186 0.718908 0.637194 0.748828 0.660428 0.002321 0.002785 0.002810 0.002245 0.006368 0.004426 0.002994 0.002613 0.508197 0.957746 0.809249 0.746032 0.497959 0.995918 0.683168 0.585254 0.496918 0.848890 0.692686 0.634612 0.491212 0.492734 0.596994 0.558059 0.003603 0.012522 0.017839 0.015241 0.002220 0.168270 0.014712 0.007247 -0.846313 -0.069260 0.488846 0.000545 0.000305 0.000813 2.929688 1.190186 3.580729 -0.863563 -0.084855 0.464930 -0.000007 2.042809e-06 -2.849968e-06 0.048335 -0.042143 0.040023 0.006822 0.005053 0.009881 0.000240 0.000117 0.000297 0.712536 0.499915 0.939672 0.999344 0.062317 -0.159836 0.001187 0.001328 0.001074 3.255208 3.320312 4.882812 0.965975 -0.000925 -0.259182 0.000032 6.406250e-05 -0.000024 -0.095776 -0.165980 0.144850 0.015653 0.019206 0.046904 0.000333 0.000457 0.000460 1.187168 1.426576 1.346959 0.164387 0.492346 0.149139 -0.843806 0.051026 0.074743 0.071737 8.423988 6.857490 10.689540 2084.369900 445.379626 810.506826 0.160231 0.490322 0.145928 -0.844157 -0.003892 -0.003804 -0.018201 -0.036467 0.077885 -0.006631 26.988689 -7.739067 -51.168052 0.002767 0.001331 0.002246 0.000222 0.031651 0.021172 0.067094 1.891410 1.482885 4.074346 324.990077 135.612823 500.564267 0.618863 -0.150822 -0.754349 -0.114060 0.383834 0.784153 0.553013 11.380460 29.010612 33.358820 2752.365093 6546.331906 2181.850987 0.596188 -0.163353 -0.775710 -0.124714 0.021907 0.013755 0.012748 -1.111580 -0.334962 0.021466 -90.668628 -64.601575 35.073660 0.015482 0.009833 0.014861 0.007212 0.166403 0.417988 0.173217 7.359519 14.858287 9.153837 744.182656 1454.186126 769.701026
2 0.685950 0.728205 0.849162 0.607438 0.777108 0.700535 0.87500 0.733333 0.497469 0.612832 0.666206 0.492255 0.718535 0.637126 0.748788 0.660685 0.011144 0.006879 0.009090 0.007845 0.005614 0.004051 0.005506 0.004440 0.516393 0.936620 0.832370 0.751323 0.995918 0.995918 0.698020 0.622120 0.496948 0.848779 0.691786 0.634099 0.486646 0.498963 0.595900 0.557786 0.003032 0.007777 0.009667 0.009077 0.043924 0.108942 0.010389 0.006009 -0.713501 0.048904 0.572830 0.006123 0.002393 0.002616 15.869141 6.692325 6.749770 -0.868275 -0.069352 0.459729 -0.000030 -6.790516e-07 -3.816164e-06 0.042151 0.006334 -0.003044 0.024366 0.017504 0.021913 0.000905 0.000376 0.000411 1.608533 0.921114 1.017115 1.060379 0.134583 -0.014328 0.001955 0.002280 0.005502 11.568510 13.627486 7.359096 0.978988 -0.000388 -0.202378 0.000005 2.112100e-07 -0.000013 -0.005919 -0.001242 0.023884 0.015082 0.015613 0.041390 0.000334 0.000404 0.000483 1.085616 1.194701 1.336285 0.168521 0.505227 0.142912 -0.835808 0.316624 0.593621 0.331014 19.806659 22.033338 26.051293 2206.180328 2613.281789 2713.864594 0.155634 0.496838 0.135235 -0.842923 -0.001639 -0.004225 0.000291 -0.003520 -0.114047 0.050148 1.585695 -0.670795 3.401131 0.005331 0.007307 0.004144 0.004806 0.054181 0.088889 0.070436 2.939673 3.487398 4.355037 268.202026 277.300592 448.167800 0.647831 -0.136257 -0.732800 -0.102524 0.879971 1.989502 1.122907 49.389847 85.475258 61.100255 4256.775521 8723.328584 4294.956003 0.619735 -0.153120 -0.759202 -0.124798 0.001542 0.004674 -0.003122 0.079193 0.174868 0.141086 4.852312 18.350814 2.436863 0.012631 0.008083 0.012225 0.012151 0.123687 0.282669 0.113030 4.806996 10.779876 6.534156 486.415887 1142.095742 625.153662
3 0.512397 0.661538 0.754190 0.512397 0.759036 0.673797 0.76250 0.677778 0.497326 0.612893 0.666100 0.484996 0.718373 0.637000 0.748664 0.660854 0.004125 0.014409 0.021173 0.058099 0.007076 0.005177 0.005281 0.004803 0.516393 0.873239 0.716763 0.666667 0.493878 0.497959 0.643564 0.580645 0.496862 0.848702 0.691813 0.634084 0.491064 0.493647 0.593827 0.557622 0.003913 0.006136 0.005968 0.004635 0.002087 0.001368 0.008473 0.005300 -0.724731 0.207108 0.604568 0.001240 0.002000 0.000923 6.787109 3.352865 2.838135 -0.789386 0.166772 0.569221 -0.000017 5.648744e-06 6.577436e-06 0.128443 -0.119382 0.047230 0.021868 0.015788 0.017773 0.000546 0.000486 0.000461 1.863614 1.430691 1.313220 1.033524 0.126770 0.421707 0.001523 0.000680 0.001583 5.789621 3.756010 5.208333 0.939998 0.078811 0.345779 -0.000055 -9.718750e-05 -0.000015 0.111309 0.174966 -0.011341 0.032360 0.014418 0.032139 0.000701 0.000572 0.000436 1.909429 1.065716 1.424733 0.211566 0.465286 0.013511 -0.859402 0.093546 0.263660 0.136374 10.712655 24.969117 24.077240 2666.816885 1920.723426 5029.040161 0.205977 0.460094 0.012212 -0.863552 0.000240 0.012612 -0.032937 0.277966 0.539358 -0.114937 39.024051 -14.919398 87.718777 0.002371 0.002726 0.000789 0.001891 0.062111 0.086016 0.096223 3.429911 6.023802 6.526026 441.445219 477.288587 875.383706 0.733975 -0.215858 -0.515914 -0.370804 0.271520 0.413471 0.793342 29.883033 33.672845 86.168465 3965.979471 4675.769180 11733.432855 0.726422 -0.222149 -0.527491 -0.380252 -0.081652 -0.042828 0.027246 -1.330705 -1.340691 1.024436 -49.463745 -93.159203 -58.539333 0.005213 0.004116 0.008078 0.003958 0.198462 0.183171 0.155875 11.152448 9.963270 16.088213 1150.663729 1135.642103 2119.655762
4 0.504132 0.635897 0.737430 1.000000 0.746988 0.652406 0.76250 0.672222 0.497305 0.612760 0.666103 0.539813 0.720609 0.636990 0.748779 0.661079 0.003440 0.007323 0.011248 0.095872 0.007634 0.003822 0.004761 0.004264 0.512295 0.866197 0.710983 0.650794 0.497959 0.497959 0.722772 0.599078 0.496943 0.848932 0.691707 0.633865 0.491129 0.493722 0.594159 0.558040 0.003295 0.004746 0.003927 0.004114 0.002148 0.001221 0.017247 0.007301 -0.774048 0.188553 0.582108 0.000586 0.000533 0.000714 2.859933 1.497396 2.392578 -0.796210 0.169789 0.556567 -0.000016 1.522640e-05 -6.975446e-08 0.037976 -0.004908 0.032503 0.010191 0.008518 0.010531 0.000297 0.000196 0.000290 0.819147 0.545627 0.845935 1.021317 0.099915 0.340652 0.002075 0.001179 0.000612 3.200955 1.819957 1.864347 0.956346 0.070920 0.300213 0.000043 9.736328e-06 -0.000034 -0.036841 -0.036219 0.075440 0.021201 0.012754 0.029698 0.000486 0.000285 0.000374 1.348408 0.832293 0.830523 0.202624 0.467448 0.012214 -0.860776 0.052285 0.040986 0.116178 2.856049 3.770583 15.126930 312.982165 281.025841 1062.566337 0.200699 0.466227 0.007997 -0.861557 -0.006016 -0.012182 -0.007998 0.021963 0.064504 0.191972 7.439429 3.549816 8.698628 0.001243 0.001357 0.001932 0.000563 0.026385 0.029268 0.078408 1.107083 1.317382 4.622568 85.712120 106.001201 406.024850 0.722931 -0.229336 -0.534479 -0.366098 0.563110 0.565189 0.085749 12.485845 20.251992 7.395605 1233.738922 2111.723609 964.527774 0.715442 -0.232278 -0.544587 -0.370770 0.045293 0.053730 -0.001529 -0.013939 0.110153 -0.246766 -31.768089 -36.879092 -7.538979 0.006682 0.002770 0.009360 0.002573 0.181719 0.217952 0.053026 5.253641 7.297097 3.331552 548.393076 819.998059 375.285448
In [6]:
physical_df.head()
Out[6]:
participant_id clothes_id property_id property_name interaction_id rating rating_level rating_level_num sub_window_num subwindow_start_time subwindow_end_time max_ch1_Hand0 max_ch2_Hand0 max_ch3_Hand0 max_ch4_Hand0 max_ch5_Hand0 max_ch6_Hand0 max_ch7_Hand0 max_ch8_Hand0 mean_ch1_Hand0 mean_ch2_Hand0 mean_ch3_Hand0 mean_ch4_Hand0 mean_ch5_Hand0 mean_ch6_Hand0 mean_ch7_Hand0 mean_ch8_Hand0 std_ch1_Hand0 std_ch2_Hand0 std_ch3_Hand0 std_ch4_Hand0 std_ch5_Hand0 std_ch6_Hand0 std_ch7_Hand0 std_ch8_Hand0 max_ch1_Hand1 max_ch2_Hand1 max_ch3_Hand1 max_ch4_Hand1 max_ch5_Hand1 max_ch6_Hand1 max_ch7_Hand1 max_ch8_Hand1 mean_ch1_Hand1 mean_ch2_Hand1 mean_ch3_Hand1 mean_ch4_Hand1 mean_ch5_Hand1 mean_ch6_Hand1 mean_ch7_Hand1 mean_ch8_Hand1 std_ch1_Hand1 std_ch2_Hand1 std_ch3_Hand1 std_ch4_Hand1 std_ch5_Hand1 std_ch6_Hand1 std_ch7_Hand1 std_ch8_Hand1 max_Ax_Hand0 max_Ay_Hand0 max_Az_Hand0 max_Vx_Hand0 max_Vy_Hand0 max_Vz_Hand0 max_Jx_Hand0 max_Jy_Hand0 max_Jz_Hand0 mean_Ax_Hand0 mean_Ay_Hand0 mean_Az_Hand0 mean_Vx_Hand0 mean_Vy_Hand0 mean_Vz_Hand0 mean_Jx_Hand0 mean_Jy_Hand0 mean_Jz_Hand0 std_Ax_Hand0 std_Ay_Hand0 std_Az_Hand0 std_Vx_Hand0 std_Vy_Hand0 std_Vz_Hand0 std_Jx_Hand0 std_Jy_Hand0 std_Jz_Hand0 max_Ax_Hand1 max_Ay_Hand1 max_Az_Hand1 max_Vx_Hand1 max_Vy_Hand1 max_Vz_Hand1 max_Jx_Hand1 max_Jy_Hand1 max_Jz_Hand1 mean_Ax_Hand1 mean_Ay_Hand1 mean_Az_Hand1 mean_Vx_Hand1 mean_Vy_Hand1 mean_Vz_Hand1 mean_Jx_Hand1 mean_Jy_Hand1 mean_Jz_Hand1 std_Ax_Hand1 std_Ay_Hand1 std_Az_Hand1 std_Vx_Hand1 std_Vy_Hand1 std_Vz_Hand1 std_Jx_Hand1 std_Jy_Hand1 std_Jz_Hand1 max_w_Hand0 max_x_Hand0 max_y_Hand0 max_z_Hand0 max_AVx_Hand0 max_AVy_Hand0 max_AVz_Hand0 max_AAx_Hand0 max_AAy_Hand0 max_AAz_Hand0 max_AJx_Hand0 max_AJy_Hand0 max_AJz_Hand0 mean_w_Hand0 mean_x_Hand0 mean_y_Hand0 mean_z_Hand0 mean_AVx_Hand0 mean_AVy_Hand0 mean_AVz_Hand0 mean_AAx_Hand0 mean_AAy_Hand0 mean_AAz_Hand0 mean_AJx_Hand0 mean_AJy_Hand0 mean_AJz_Hand0 std_w_Hand0 std_x_Hand0 std_y_Hand0 std_z_Hand0 std_AVx_Hand0 std_AVy_Hand0 std_AVz_Hand0 std_AAx_Hand0 std_AAy_Hand0 std_AAz_Hand0 std_AJx_Hand0 std_AJy_Hand0 std_AJz_Hand0 max_w_Hand1 max_x_Hand1 max_y_Hand1 max_z_Hand1 max_AVx_Hand1 max_AVy_Hand1 max_AVz_Hand1 max_AAx_Hand1 max_AAy_Hand1 max_AAz_Hand1 max_AJx_Hand1 max_AJy_Hand1 max_AJz_Hand1 mean_w_Hand1 mean_x_Hand1 mean_y_Hand1 mean_z_Hand1 mean_AVx_Hand1 mean_AVy_Hand1 mean_AVz_Hand1 mean_AAx_Hand1 mean_AAy_Hand1 mean_AAz_Hand1 mean_AJx_Hand1 mean_AJy_Hand1 mean_AJz_Hand1 std_w_Hand1 std_x_Hand1 std_y_Hand1 std_z_Hand1 std_AVx_Hand1 std_AVy_Hand1 std_AVz_Hand1 std_AAx_Hand1 std_AAy_Hand1 std_AAz_Hand1 std_AJx_Hand1 std_AJy_Hand1 std_AJz_Hand1
0 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.481 2021-08-05 13:21:32.468 0.504132 0.620513 0.675978 0.500000 0.759036 0.652406 0.76250 0.666667 0.497498 0.612780 0.665895 0.492285 0.718526 0.636907 0.748853 0.660720 0.002329 0.002760 0.003011 0.002201 0.006194 0.004289 0.003634 0.002595 0.508197 0.929578 0.757225 0.730159 0.497959 0.995918 0.663366 0.580645 0.497102 0.848495 0.692072 0.634859 0.491574 0.511567 0.596728 0.558018 0.003056 0.009851 0.011220 0.016046 0.002283 0.125342 0.014496 0.005100 -0.850708 -0.068771 0.490311 0.000525 0.000406 0.000903 1.269531 1.220703 2.258301 -0.863979 -0.089162 0.468123 -0.000005 1.483398e-05 -1.191406e-05 -0.010928 -0.052313 0.060087 0.006994 0.008424 0.010178 0.000201 0.000180 0.000270 0.599364 0.630856 0.794158 1.023270 0.042786 -0.178879 0.001218 0.001529 0.001429 4.089355 5.468750 3.271484 0.970242 -0.011443 -0.239064 -0.000030 -8.115234e-06 0.000065 0.061211 0.036287 -0.170119 0.017187 0.014988 0.034359 0.000440 0.000417 0.000641 1.262790 1.374306 1.977670 0.179352 0.488418 0.160615 -0.840857 0.133141 0.061469 0.117029 4.332320 2.887801 19.812834 554.574503 316.450316 1338.775861 0.171550 0.486515 0.155002 -0.842509 -0.002358 -0.006487 -0.037808 -0.069210 0.040128 0.213198 -18.896953 -5.997847 29.264918 0.004033 0.001122 0.003172 0.000812 0.034035 0.027288 0.100030 1.808784 1.349269 6.515867 214.502864 135.316892 572.754308 0.618680 -0.175326 -0.753378 -0.128901 0.215491 0.583907 0.275227 21.603607 56.450019 29.424453 2797.763022 9050.317251 2366.953044 0.602964 -0.177295 -0.766545 -0.131596 -0.011132 -0.035192 -0.000290 -0.692534 -0.994509 -0.440578 19.388504 94.341574 -56.539654 0.007223 0.001357 0.006089 0.001773 0.140168 0.419609 0.109731 8.409602 20.970763 7.985693 769.853603 1878.284384 898.072858
1 7 14 3 smoothness 1 3 medium 2 2 2021-08-05 13:21:32.495 2021-08-05 13:21:33.464 0.504132 0.620513 0.675978 0.500000 0.759036 0.663102 0.75625 0.666667 0.497417 0.612789 0.666077 0.492186 0.718908 0.637194 0.748828 0.660428 0.002321 0.002785 0.002810 0.002245 0.006368 0.004426 0.002994 0.002613 0.508197 0.957746 0.809249 0.746032 0.497959 0.995918 0.683168 0.585254 0.496918 0.848890 0.692686 0.634612 0.491212 0.492734 0.596994 0.558059 0.003603 0.012522 0.017839 0.015241 0.002220 0.168270 0.014712 0.007247 -0.846313 -0.069260 0.488846 0.000545 0.000305 0.000813 2.929688 1.190186 3.580729 -0.863563 -0.084855 0.464930 -0.000007 2.042809e-06 -2.849968e-06 0.048335 -0.042143 0.040023 0.006822 0.005053 0.009881 0.000240 0.000117 0.000297 0.712536 0.499915 0.939672 0.999344 0.062317 -0.159836 0.001187 0.001328 0.001074 3.255208 3.320312 4.882812 0.965975 -0.000925 -0.259182 0.000032 6.406250e-05 -0.000024 -0.095776 -0.165980 0.144850 0.015653 0.019206 0.046904 0.000333 0.000457 0.000460 1.187168 1.426576 1.346959 0.164387 0.492346 0.149139 -0.843806 0.051026 0.074743 0.071737 8.423988 6.857490 10.689540 2084.369900 445.379626 810.506826 0.160231 0.490322 0.145928 -0.844157 -0.003892 -0.003804 -0.018201 -0.036467 0.077885 -0.006631 26.988689 -7.739067 -51.168052 0.002767 0.001331 0.002246 0.000222 0.031651 0.021172 0.067094 1.891410 1.482885 4.074346 324.990077 135.612823 500.564267 0.618863 -0.150822 -0.754349 -0.114060 0.383834 0.784153 0.553013 11.380460 29.010612 33.358820 2752.365093 6546.331906 2181.850987 0.596188 -0.163353 -0.775710 -0.124714 0.021907 0.013755 0.012748 -1.111580 -0.334962 0.021466 -90.668628 -64.601575 35.073660 0.015482 0.009833 0.014861 0.007212 0.166403 0.417988 0.173217 7.359519 14.858287 9.153837 744.182656 1454.186126 769.701026
2 7 14 3 smoothness 1 3 medium 2 3 2021-08-05 13:21:33.513 2021-08-05 13:21:46.475 0.685950 0.728205 0.849162 0.607438 0.777108 0.700535 0.87500 0.733333 0.497469 0.612832 0.666206 0.492255 0.718535 0.637126 0.748788 0.660685 0.011144 0.006879 0.009090 0.007845 0.005614 0.004051 0.005506 0.004440 0.516393 0.936620 0.832370 0.751323 0.995918 0.995918 0.698020 0.622120 0.496948 0.848779 0.691786 0.634099 0.486646 0.498963 0.595900 0.557786 0.003032 0.007777 0.009667 0.009077 0.043924 0.108942 0.010389 0.006009 -0.713501 0.048904 0.572830 0.006123 0.002393 0.002616 15.869141 6.692325 6.749770 -0.868275 -0.069352 0.459729 -0.000030 -6.790516e-07 -3.816164e-06 0.042151 0.006334 -0.003044 0.024366 0.017504 0.021913 0.000905 0.000376 0.000411 1.608533 0.921114 1.017115 1.060379 0.134583 -0.014328 0.001955 0.002280 0.005502 11.568510 13.627486 7.359096 0.978988 -0.000388 -0.202378 0.000005 2.112100e-07 -0.000013 -0.005919 -0.001242 0.023884 0.015082 0.015613 0.041390 0.000334 0.000404 0.000483 1.085616 1.194701 1.336285 0.168521 0.505227 0.142912 -0.835808 0.316624 0.593621 0.331014 19.806659 22.033338 26.051293 2206.180328 2613.281789 2713.864594 0.155634 0.496838 0.135235 -0.842923 -0.001639 -0.004225 0.000291 -0.003520 -0.114047 0.050148 1.585695 -0.670795 3.401131 0.005331 0.007307 0.004144 0.004806 0.054181 0.088889 0.070436 2.939673 3.487398 4.355037 268.202026 277.300592 448.167800 0.647831 -0.136257 -0.732800 -0.102524 0.879971 1.989502 1.122907 49.389847 85.475258 61.100255 4256.775521 8723.328584 4294.956003 0.619735 -0.153120 -0.759202 -0.124798 0.001542 0.004674 -0.003122 0.079193 0.174868 0.141086 4.852312 18.350814 2.436863 0.012631 0.008083 0.012225 0.012151 0.123687 0.282669 0.113030 4.806996 10.779876 6.534156 486.415887 1142.095742 625.153662
3 7 14 4 thickness 2 5 medium 2 1 2021-08-05 13:22:02.060 2021-08-05 13:22:03.029 0.512397 0.661538 0.754190 0.512397 0.759036 0.673797 0.76250 0.677778 0.497326 0.612893 0.666100 0.484996 0.718373 0.637000 0.748664 0.660854 0.004125 0.014409 0.021173 0.058099 0.007076 0.005177 0.005281 0.004803 0.516393 0.873239 0.716763 0.666667 0.493878 0.497959 0.643564 0.580645 0.496862 0.848702 0.691813 0.634084 0.491064 0.493647 0.593827 0.557622 0.003913 0.006136 0.005968 0.004635 0.002087 0.001368 0.008473 0.005300 -0.724731 0.207108 0.604568 0.001240 0.002000 0.000923 6.787109 3.352865 2.838135 -0.789386 0.166772 0.569221 -0.000017 5.648744e-06 6.577436e-06 0.128443 -0.119382 0.047230 0.021868 0.015788 0.017773 0.000546 0.000486 0.000461 1.863614 1.430691 1.313220 1.033524 0.126770 0.421707 0.001523 0.000680 0.001583 5.789621 3.756010 5.208333 0.939998 0.078811 0.345779 -0.000055 -9.718750e-05 -0.000015 0.111309 0.174966 -0.011341 0.032360 0.014418 0.032139 0.000701 0.000572 0.000436 1.909429 1.065716 1.424733 0.211566 0.465286 0.013511 -0.859402 0.093546 0.263660 0.136374 10.712655 24.969117 24.077240 2666.816885 1920.723426 5029.040161 0.205977 0.460094 0.012212 -0.863552 0.000240 0.012612 -0.032937 0.277966 0.539358 -0.114937 39.024051 -14.919398 87.718777 0.002371 0.002726 0.000789 0.001891 0.062111 0.086016 0.096223 3.429911 6.023802 6.526026 441.445219 477.288587 875.383706 0.733975 -0.215858 -0.515914 -0.370804 0.271520 0.413471 0.793342 29.883033 33.672845 86.168465 3965.979471 4675.769180 11733.432855 0.726422 -0.222149 -0.527491 -0.380252 -0.081652 -0.042828 0.027246 -1.330705 -1.340691 1.024436 -49.463745 -93.159203 -58.539333 0.005213 0.004116 0.008078 0.003958 0.198462 0.183171 0.155875 11.152448 9.963270 16.088213 1150.663729 1135.642103 2119.655762
4 7 14 4 thickness 2 5 medium 2 2 2021-08-05 13:22:03.061 2021-08-05 13:22:04.047 0.504132 0.635897 0.737430 1.000000 0.746988 0.652406 0.76250 0.672222 0.497305 0.612760 0.666103 0.539813 0.720609 0.636990 0.748779 0.661079 0.003440 0.007323 0.011248 0.095872 0.007634 0.003822 0.004761 0.004264 0.512295 0.866197 0.710983 0.650794 0.497959 0.497959 0.722772 0.599078 0.496943 0.848932 0.691707 0.633865 0.491129 0.493722 0.594159 0.558040 0.003295 0.004746 0.003927 0.004114 0.002148 0.001221 0.017247 0.007301 -0.774048 0.188553 0.582108 0.000586 0.000533 0.000714 2.859933 1.497396 2.392578 -0.796210 0.169789 0.556567 -0.000016 1.522640e-05 -6.975446e-08 0.037976 -0.004908 0.032503 0.010191 0.008518 0.010531 0.000297 0.000196 0.000290 0.819147 0.545627 0.845935 1.021317 0.099915 0.340652 0.002075 0.001179 0.000612 3.200955 1.819957 1.864347 0.956346 0.070920 0.300213 0.000043 9.736328e-06 -0.000034 -0.036841 -0.036219 0.075440 0.021201 0.012754 0.029698 0.000486 0.000285 0.000374 1.348408 0.832293 0.830523 0.202624 0.467448 0.012214 -0.860776 0.052285 0.040986 0.116178 2.856049 3.770583 15.126930 312.982165 281.025841 1062.566337 0.200699 0.466227 0.007997 -0.861557 -0.006016 -0.012182 -0.007998 0.021963 0.064504 0.191972 7.439429 3.549816 8.698628 0.001243 0.001357 0.001932 0.000563 0.026385 0.029268 0.078408 1.107083 1.317382 4.622568 85.712120 106.001201 406.024850 0.722931 -0.229336 -0.534479 -0.366098 0.563110 0.565189 0.085749 12.485845 20.251992 7.395605 1233.738922 2111.723609 964.527774 0.715442 -0.232278 -0.544587 -0.370770 0.045293 0.053730 -0.001529 -0.013939 0.110153 -0.246766 -31.768089 -36.879092 -7.538979 0.006682 0.002770 0.009360 0.002573 0.181719 0.217952 0.053026 5.253641 7.297097 3.331552 548.393076 819.998059 375.285448

15 window emg¶

In [7]:
path_emg_0 = "/Users/niharawarawita/Desktop/MSc Project/Data and code/emg_0_15subwindows.csv"
emg_0_15 = pd.read_csv(path_emg_0)
emg_0_15.head(10)
Out[7]:
participant_id clothes_id property_id property_name interaction_id rating rating_level rating_level_num sub_window_num subwindow_start_time subwindow_end_time mean_ch1 mean_ch2 mean_ch3 mean_ch4 mean_ch5 mean_ch6 mean_ch7 mean_ch8
0 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.481 2021-08-05 13:21:32.468 0.497676 0.613782 0.665852 0.491478 0.719126 0.635695 0.748047 0.661458
1 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.481 2021-08-05 13:21:32.468 0.497676 0.612500 0.666201 0.492511 0.719126 0.636030 0.748828 0.661458
2 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.481 2021-08-05 13:21:32.468 0.497934 0.613782 0.665503 0.492252 0.718750 0.636698 0.749609 0.659722
3 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.481 2021-08-05 13:21:32.468 0.497934 0.613782 0.665502 0.492511 0.717620 0.636364 0.749219 0.660764
4 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.481 2021-08-05 13:21:32.468 0.497676 0.612500 0.666201 0.493027 0.715738 0.634693 0.748828 0.661806
5 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.481 2021-08-05 13:21:32.468 0.496643 0.612179 0.666201 0.492252 0.719880 0.637366 0.749609 0.661806
6 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.481 2021-08-05 13:21:32.468 0.497676 0.613141 0.664804 0.492511 0.717620 0.635361 0.750391 0.660764
7 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.481 2021-08-05 13:21:32.468 0.497934 0.612820 0.665852 0.493027 0.717620 0.637366 0.748047 0.661806
8 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.481 2021-08-05 13:21:32.468 0.497676 0.613462 0.666201 0.492252 0.717997 0.637032 0.748828 0.661111
9 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.481 2021-08-05 13:21:32.468 0.496901 0.611538 0.666550 0.492252 0.719503 0.636030 0.748047 0.660069
In [8]:
path_emg_1 = "/Users/niharawarawita/Desktop/MSc Project/Data and code/emg_1_15subwindows.csv"
emg_1_15 = pd.read_csv(path_emg_1)
emg_1_15.head(10)
Out[8]:
participant_id clothes_id property_id property_name interaction_id rating rating_level rating_level_num sub_window_num subwindow_start_time subwindow_end_time mean_ch1 mean_ch2 mean_ch3 mean_ch4 mean_ch5 mean_ch6 mean_ch7 mean_ch8
0 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.489 2021-08-05 13:21:32.480 0.496926 0.847271 0.693642 0.638228 0.491072 0.485714 0.593750 0.559332
1 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.489 2021-08-05 13:21:32.480 0.496414 0.844630 0.689306 0.638228 0.491582 0.525000 0.599319 0.559620
2 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.489 2021-08-05 13:21:32.480 0.496670 0.848591 0.691835 0.632275 0.491582 0.815306 0.611077 0.557604
3 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.489 2021-08-05 13:21:32.480 0.497439 0.850792 0.692558 0.635252 0.492347 0.544388 0.599629 0.558468
4 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.489 2021-08-05 13:21:32.480 0.496926 0.849472 0.695809 0.636574 0.492347 0.476786 0.594678 0.557028
5 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.489 2021-08-05 13:21:32.480 0.497439 0.848591 0.690390 0.635252 0.491072 0.479592 0.594988 0.557316
6 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.489 2021-08-05 13:21:32.480 0.497695 0.849472 0.691113 0.634590 0.492092 0.514541 0.594988 0.557604
7 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.489 2021-08-05 13:21:32.480 0.497439 0.846831 0.691474 0.634590 0.491327 0.486225 0.594988 0.557316
8 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.489 2021-08-05 13:21:32.480 0.497183 0.847711 0.691113 0.634590 0.491582 0.489286 0.596225 0.558180
9 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.489 2021-08-05 13:21:32.480 0.497183 0.848591 0.692197 0.632937 0.491072 0.452806 0.593440 0.558468
In [9]:
# Remove enjoyment as we are only considering physical properties
emg_0_15 = emg_0_15[emg_0_15.property_name!='enjoyment']
emg_1_15 = emg_1_15[emg_1_15.property_name!='enjoyment']
#emg_1_15
In [10]:
# Obtain a df of features
features_emg_0 = emg_0_15.iloc[:,11:]

features_emg_1 = emg_1_15.iloc[:,11:]
features_emg_1.head()
Out[10]:
mean_ch1 mean_ch2 mean_ch3 mean_ch4 mean_ch5 mean_ch6 mean_ch7 mean_ch8
0 0.496926 0.847271 0.693642 0.638228 0.491072 0.485714 0.593750 0.559332
1 0.496414 0.844630 0.689306 0.638228 0.491582 0.525000 0.599319 0.559620
2 0.496670 0.848591 0.691835 0.632275 0.491582 0.815306 0.611077 0.557604
3 0.497439 0.850792 0.692558 0.635252 0.492347 0.544388 0.599629 0.558468
4 0.496926 0.849472 0.695809 0.636574 0.492347 0.476786 0.594678 0.557028

Normalise the data¶

3 window combined df¶

In [11]:
normalised_features_df = features_df.copy()
print(normalised_features_df.shape)
(1260, 180)
In [12]:
# create scaler
scaler = MinMaxScaler(feature_range=(-1,1)) # As this is the range of the activation function - tanh

# fit scaler and apply transform
normalised_features_df[normalised_features_df.columns] = scaler.fit_transform(features_df[features_df.columns])
normalised_features_df.shape
Out[12]:
(1260, 180)
In [13]:
df_info = physical_df.iloc[:, :11]
df_info.head()
Out[13]:
participant_id clothes_id property_id property_name interaction_id rating rating_level rating_level_num sub_window_num subwindow_start_time subwindow_end_time
0 7 14 3 smoothness 1 3 medium 2 1 2021-08-05 13:21:31.481 2021-08-05 13:21:32.468
1 7 14 3 smoothness 1 3 medium 2 2 2021-08-05 13:21:32.495 2021-08-05 13:21:33.464
2 7 14 3 smoothness 1 3 medium 2 3 2021-08-05 13:21:33.513 2021-08-05 13:21:46.475
3 7 14 4 thickness 2 5 medium 2 1 2021-08-05 13:22:02.060 2021-08-05 13:22:03.029
4 7 14 4 thickness 2 5 medium 2 2 2021-08-05 13:22:03.061 2021-08-05 13:22:04.047
In [14]:
normalised_df = pd.concat([df_info,normalised_features_df], axis=1)
normalised_df.shape
Out[14]:
(1260, 191)

15 window emg¶

In [15]:
normalised_features_emg_0 = features_emg_0.copy()
normalised_features_emg_1 = features_emg_1.copy()
In [16]:
# create scaler
scaler = MinMaxScaler(feature_range=(-1,1)) # As this is the range of the activation function - tanh

# fit scaler and apply transform
normalised_features_emg_0[normalised_features_emg_0.columns] = scaler.fit_transform(features_emg_0[features_emg_0.columns])
normalised_features_emg_1[normalised_features_emg_1.columns] = scaler.fit_transform(features_emg_1[features_emg_1.columns])
In [17]:
df_info_0 = features_emg_0.iloc[:, :11]
df_info_1 = features_emg_1.iloc[:, :11]
In [18]:
normalised_emg_0 = pd.concat([df_info_0, normalised_features_emg_0], axis=1)
normalised_emg_1 = pd.concat([df_info_1, normalised_features_emg_1], axis=1)
In [19]:
normalised_emg_1.shape
Out[19]:
(190889, 16)

Create X and y data¶

In [20]:
def create_X_2d(df, features_starting_idx):
    
    X_2d = df.iloc[:,features_starting_idx:].values
    
    X_tensor_2d = torch.Tensor(X_2d)    
    return X_tensor_2d
In [134]:
def create_y_train_for_2d_X(df, predicting_feature = 'property_id', output_as_tensor='Yes'):
    # CreatE an instance of a one-hot-encoder
    encoder = OneHotEncoder(handle_unknown='ignore')

    # Perform one-hot encoding on the specified column 
    encoder_df = pd.DataFrame(encoder.fit_transform(df[[predicting_feature]]).toarray())
    
    # Convert to a numpy array
    y_train = encoder_df.to_numpy()
    
    if output_as_tensor == 'Yes':
        # Convert to a tensor
        y_train = torch.Tensor(y_train)

    return y_train
In [22]:
def create_y_test_for_2d_X(df, predicting_feature = 'property_id'):   
    y_test = df[predicting_feature].values
    if predicting_feature == 'property_id':
        y_test = y_test - 3
    elif predicting_feature == 'rating_level_num':
        y_test = y_test - 1
    
    y_test_tensor = torch.Tensor(y_test)    
    y_test_tensor = y_test_tensor.type(torch.LongTensor)
    
    return y_test_tensor
In [23]:
def create_X_3d(df, features_starting_idx):
    dim1 = df.interaction_id.nunique()
    #num_timestamps_per_interaction = df.groupby('interaction_id')['sub_window_num'].nunique()
    dim2 = df.sub_window_num.nunique()
    dim3 = df.iloc[:,features_starting_idx:].shape[1]
        
    X = np.zeros((dim1, dim2, dim3)) 

    itr_id_lst = df.interaction_id.unique().tolist()

    for i in range(len(itr_id_lst)):
        itr_id = itr_id_lst[i]
        itr_id_df = df[df.interaction_id==itr_id]  
        
        for j in range(itr_id_df.shape[0]):
            vals_arr = itr_id_df.iloc[j,features_starting_idx:].values
            X[i,j] = vals_arr
    
    X_tensor = torch.Tensor(X)    
    return X_tensor
In [24]:
def create_y_train_for_3d_X(df, predicting_feature = 'property_id'):
    # Create a dataset with only the required columns
    df2 = df[['participant_id', 'clothes_id', 'property_id', 'rating_level_num']]

    # Remove duplicates
    df2.drop_duplicates(keep='first', inplace=True)

    # Reset the indexes
    df2.reset_index(drop=True, inplace=True) 
    
    ## Create y train
    # CreatE an instance of a one-hot-encoder
    encoder = OneHotEncoder(handle_unknown='ignore')

    # Perform one-hot encoding on the specified column 
    encoder_df = pd.DataFrame(encoder.fit_transform(df2[[predicting_feature]]).toarray())
    
    # Convert to a numpy array
    y_train = encoder_df.to_numpy()
    
    # Convert to a tensor
    y_train = torch.Tensor(y_train)
  
    return y_train
In [25]:
def create_y_test_for_3d_X(df, predicting_feature = 'property_id'):
    # Create a dataset with only the required columns
    df2 = df[['participant_id', 'clothes_id', 'property_id', 'rating_level_num']]

    # Remove duplicates
    df2.drop_duplicates(keep='first', inplace=True)

    # Reset the indexes
    df2.reset_index(drop=True, inplace=True) 
    
    y_test = df2[predicting_feature].values
    if predicting_feature == 'property_id':
        y_test = y_test - 3
    elif predicting_feature == 'rating_level_num':
        y_test = y_test - 1
    
    y_test = torch.Tensor(y_test)    
    y_test = y_test.type(torch.LongTensor)
    
    return y_test

Model 1 - Linear model using all 180 features¶

Create the model¶

In [126]:
class Linear_all_features_properties(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(180, 20)
        self.fc2 = nn.Linear(20, 10)
        self.fc3 = nn.Linear(10, 5)        
           
    def forward(self, x): #, x2
        x = F.tanh(self.fc1(x))
        x = F.tanh(self.fc2(x))
        x = F.softmax(self.fc3(x), dim=1)
        return x

class Linear_all_features_ratings(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(185, 20)
        self.fc2 = nn.Linear(20, 10)
        self.fc3 = nn.Linear(10, 3)        

    def forward(self, x): #, x2
        x = F.tanh(self.fc1(x))
        x = F.tanh(self.fc2(x))
        x = F.softmax(self.fc3(x), dim=1)
        return x
 
In [135]:
def find_best_model_for_2d_X(train_dataloader, val_dataloader, learning_rate, num_epochs, model):

    # Model
    train_model = model

    # Loss and Optimiser
    criterion = torch.nn.CrossEntropyLoss()
    optimizer = optim.SGD(train_model.parameters(), lr=learning_rate, momentum=0.7)

    best_avg_loss = np.inf
    best_model = None
    #best_model_epoch_num = np.inf
    train_loss_lst = []
    val_loss_lst = []
    avg_loss_lst = []

    for epoch in range(num_epochs):  # loop over the dataset multiple times

        #Set the model in training mode
        train_model.train()

        # Initialise the total training and validation loss
        epoch_train_loss = 0
        epoch_val_loss = 0
        avg_loss = 0
        #count_train = 0
        #count_val = 0

        #running_loss = 0.0
        for i, train_data in enumerate(train_dataloader, 0):
            #print(len(train_data))
            #count_train += 1
            # get the inputs; data is a list of [input1, input2, label]
            train_input1, train_labels = train_data #train_input2, 

            #train_labels = train_labels.type(torch.LongTensor)

            # zero the parameter gradients
            optimizer.zero_grad()

            # forward + backward + optimize
            train_preds = train_model(train_input1) #, train_input2
            #print(train_labels)#
            #print(train_preds)
            #print(train_labels)
            train_loss = criterion(train_preds, train_labels)
            train_loss.backward()
            optimizer.step()

            # Update training loss
            epoch_train_loss += train_loss.item()

        # Switch off auto grad for evaluation
        with torch.no_grad():

            # Set the model in evaluation mode
            train_model.eval()

            for j, val_data in enumerate(val_dataloader, 0):
               # count_val += 1
               # print(len(val_data))
            # get the inputs; data is a list of [input1, input2, label]
                val_input1, val_labels = val_data # val_input2, 

                #val_labels = val_labels.type(torch.LongTensor)

                val_preds = train_model(val_input1) #, val_input2

                # Update validation loss
                val_loss = criterion(val_preds, val_labels)

                epoch_val_loss += val_loss.item()
        #print(len(train_dataloader), len(val_dataloader))       
        avg_training_loss = epoch_train_loss / len(train_dataloader) #count_train
        avg_validation_loss = epoch_val_loss / len(val_dataloader) #count_val
        avg_loss = (avg_training_loss + avg_validation_loss) / 2
        
        train_loss_lst.append(avg_training_loss)
        val_loss_lst.append(avg_validation_loss)
        avg_loss_lst.append(avg_loss)
         
        #print(f'epoch {epoch+1}: train loss = {round(avg_training_loss,2)}, val loss = {round(avg_validation_loss,2)}, average loss = {round(avg_loss,2)}')

        if avg_loss < best_avg_loss:
            best_avg_loss = avg_loss
            best_model = train_model.state_dict()

    return best_avg_loss, best_model, train_loss_lst, val_loss_lst, avg_loss_lst   #, avg_loss_lst, 
In [139]:
# Original
def Linear_LOP0CV(data, model, num_folds=5, predicting_feature='property_id', learning_rate=0.01, num_epochs=10, random_state=num): #, num_inner_folds=5
    # Set fixed random number seed
    torch.manual_seed(num)
    
   # elif predicting_feature == 'rating_level_num':
    #weighted_f1_lst = [] 
    total_conf_mat = 0
    micro_f1_lst = []
    #macro_f1_lst = []
    acc_lst = []
    if predicting_feature == 'property_id':
        macro_f1_lst = []
    elif predicting_feature == 'rating_level_num':
        weighted_f1_lst = []    



    #lst = [6,24]
    
    for participant in sorted(data.participant_id.unique()): #lst: #:
        print(f'LEAVING PARTICIPANT {participant} OUT:')
        
        # Split the data into training and testing
        training_data = data[data.participant_id != participant] 
        testing_data = data[data.participant_id == participant] 

        # Data preparation
        X_train = create_X_2d(training_data, 11)       
        y_train = create_y_train_for_2d_X(training_data, predicting_feature = predicting_feature, output_as_tensor='Yes')
        X_test = create_X_2d(testing_data, 11) 
        y_test = create_y_test_for_2d_X(testing_data, predicting_feature = predicting_feature)
        
        #print(X_train.shape)
        #print(y_train.shape)
        #print(X_test.shape)
        #print(y_test.shape)
        #print('------------')
        
        if predicting_feature == 'rating_level_num':
            X_train_add = create_y_train_for_2d_X(training_data, predicting_feature = 'property_id', output_as_tensor='Yes')
            #X_train_add = torch.Tensor(X_train_add)    
            #print(type(X_train_add))
            #print(type(X_train))
            X_train = torch.cat((X_train_add, X_train), 1)
            #X_train = pd.concat([X_train_add, X_train], axis=1)
            X_test_add = create_y_train_for_2d_X(testing_data, predicting_feature = 'property_id', output_as_tensor='Yes')
            #X_test_add = torch.Tensor(X_test_add)   
            X_test = torch.cat((X_test_add, X_test), 1)

        
        #print(X_train.shape)
        #print(y_train)
        #print(X_test.shape)
        #print(y_test)

        # Create the datasets and dataloaders
        train_dataset = TensorDataset(X_train, y_train) 
        
        test_dataset = TensorDataset(X_test, y_test)
        test_dataloader = torch.utils.data.DataLoader(test_dataset, shuffle=True, batch_size=90) # num_workers=2,       
            
        # Configure the cross-validation procedure
        cv_inner = KFold(n_splits=num_folds, shuffle=True, random_state=num)
                
        min_avg_loss_subject = np.inf
        best_model_subject = None
        
        best_train_loss_lst = None
        best_val_loss_lst = None
        best_avg_loss_lst = None
        best_fold = np.inf

        for fold, (train_ids, val_ids) in enumerate(cv_inner.split(train_dataset)):
            #print(f'FOLD {fold+1}:')
           # print(train_ids)
            #print(val_ids)
                       
            # Sample elements randomly from a given list of ids, no replacement.
            train_subsampler = torch.utils.data.SubsetRandomSampler(train_ids) # The ids are the same for both
            val_subsampler = torch.utils.data.SubsetRandomSampler(val_ids)

            # Define data loaders for training and testing data in this fold
            train_dataloader = torch.utils.data.DataLoader(train_dataset, sampler=train_subsampler) #, batch_size=100
            val_dataloader = torch.utils.data.DataLoader(train_dataset, sampler=val_subsampler) #, batch_size=20        

            avg_loss_fold, best_model_fold, fold_train_loss_lst, fold_val_loss_lst, fold_avg_loss_lst = find_best_model_for_2d_X(train_dataloader, val_dataloader, learning_rate, num_epochs, model)
                           
            if avg_loss_fold < min_avg_loss_subject:
                min_avg_loss_subject = avg_loss_fold
                best_model_subject = best_model_fold
                best_train_loss_lst = fold_train_loss_lst
                best_val_loss_lst = fold_val_loss_lst
                best_avg_loss_lst = fold_avg_loss_lst
                best_fold = fold+1

        fig = plt.figure(f"{participant}")                  
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_train_loss_lst)
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_val_loss_lst)
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_avg_loss_lst)
        plt.title(f"Loss when participant {participant} is left out (lr={learning_rate}, num_epochs ={num_epochs})")
        plt.legend(['train loss', 'val loss', 'avg_loss'])

        # save trained model 
        name = 'model_participant_'+str(participant)+'.pt'
        torch.save(best_model_subject, name)
        print(f'The model for participant {participant} has been saved')
        
        test_model = model
        test_model.load_state_dict(torch.load(name))

        dataiter = iter(test_dataloader) 
        test_input1, test_labels = dataiter.next() 
    
        test_preds = test_model(test_input1) 
        
        test_preds_np = test_preds.detach().numpy()
        test_predicted_np = np.argmax(test_preds_np, axis = 1)
        
        test_labels_np = test_labels.numpy()       
               
        if predicting_feature == 'property_id':
            conf_mat = confusion_matrix(test_labels_np, test_predicted_np, labels=[0, 1, 2, 3, 4])
            macro_f1_score = f1_score(test_labels_np, test_predicted_np, average='macro') 
            macro_f1_lst.append(macro_f1_score) 
        elif predicting_feature == 'rating_level_num':
            conf_mat = confusion_matrix(test_labels_np, test_predicted_np, labels=[0,1,2])
            weighted_f1_score = f1_score(test_labels_np, test_predicted_np, average='weighted') 
            weighted_f1_lst.append(weighted_f1_score)
            
        total_conf_mat += conf_mat
        micro_f1_score = f1_score(test_labels_np, test_predicted_np, average='micro')  
        micro_f1_lst.append(micro_f1_score)
        acc = accuracy_score(test_labels_np, test_predicted_np)
        acc_lst.append(acc)


        print(f"Leaving participant {participant} out")
        print("(1) Confusion matrix:\n", conf_mat)
        print(f"(2) micro F1 score = {round(micro_f1_score,2)}") 
        if predicting_feature == 'property_id':
            print(f"(3) Macro F1 score = {round(macro_f1_score,2)}")
        elif predicting_feature == 'rating_level_num':
            print(f"(3) Weighted F1 score = {round(weighted_f1_score,2)}")            
        print(f"(4) Percentage Classification accuracy = {round(acc*100,2)}%")
        
        total_conf_mat += conf_mat 
        micro_f1_lst.append(micro_f1_score)
        acc_lst.append(acc)
        print('--------------------------------')
        
    avg_micro_f1_score = sum(micro_f1_lst) / len(micro_f1_lst)
    if predicting_feature == 'property_id':
        avg_macro_f1_score = sum(macro_f1_lst) / len(macro_f1_lst)  
    elif predicting_feature == 'rating_level_num':
        avg_weighted_f1_score = sum(weighted_f1_lst) / len(weighted_f1_lst)             
    avg_acc = sum(acc_lst) / len(acc_lst)   
    
    print(f'Using Leave One Participant Out CV (LOPOCV):') 
    print("(1) Confusion matrix:\n", total_conf_mat)
    print(f"(2) Average micro F1 score = {round(avg_micro_f1_score,2)}")
    if predicting_feature == 'property_id':
        print(f"(3) Average macro F1 score = {round(avg_macro_f1_score,2)}")
    elif predicting_feature == 'rating_level_num':
        print(f"(3) Average weighted F1 score = {round(avg_weighted_f1_score,2)}")      
    print(f"(4) Average Percentage Classification accuracy = {round(avg_acc*100,2)}%")
            

Run the model for properties¶

In [29]:
Linear_LOP0CV(normalised_df, model=Linear_all_features_properties(), num_folds=5, predicting_feature='property_id', learning_rate=0.005, num_epochs=150, random_state=num)
    
LEAVING PARTICIPANT 1 OUT:
The model for participant 1 has been saved
Leaving participant 1 out
(1) Confusion matrix:
 [[17  1  0  0  0]
 [10  7  0  0  1]
 [18  0  0  0  0]
 [ 3 13  0  2  0]
 [ 5 12  0  1  0]]
(2) micro F1 score = 0.29
(3) Macro F1 score = 0.19
(4) Percentage Classification accuracy = 28.89%
--------------------------------
LEAVING PARTICIPANT 2 OUT:
The model for participant 2 has been saved
Leaving participant 2 out
(1) Confusion matrix:
 [[ 6  5  1  4  2]
 [ 1 16  0  0  1]
 [ 0  3 15  0  0]
 [ 0  0  0 17  1]
 [ 2  7  0  5  4]]
(2) micro F1 score = 0.64
(3) Macro F1 score = 0.61
(4) Percentage Classification accuracy = 64.44%
--------------------------------
LEAVING PARTICIPANT 3 OUT:
The model for participant 3 has been saved
Leaving participant 3 out
(1) Confusion matrix:
 [[17  0  1  0  0]
 [ 0  1  4  5  8]
 [ 0  0  2 10  6]
 [ 0  0  1 16  1]
 [ 0  6  2  3  7]]
(2) micro F1 score = 0.48
(3) Macro F1 score = 0.43
(4) Percentage Classification accuracy = 47.78%
--------------------------------
LEAVING PARTICIPANT 4 OUT:
The model for participant 4 has been saved
Leaving participant 4 out
(1) Confusion matrix:
 [[14  1  3  0  0]
 [ 1  9  3  2  3]
 [ 0  3 12  2  1]
 [ 0  2  1 15  0]
 [ 0  3  5  4  6]]
(2) micro F1 score = 0.62
(3) Macro F1 score = 0.62
(4) Percentage Classification accuracy = 62.22%
--------------------------------
LEAVING PARTICIPANT 5 OUT:
The model for participant 5 has been saved
Leaving participant 5 out
(1) Confusion matrix:
 [[ 8  2  7  0  1]
 [ 0  1  0  0 17]
 [ 8  0  5  0  5]
 [ 0  0  0 12  6]
 [ 0  0  0  0 18]]
(2) micro F1 score = 0.49
(3) Macro F1 score = 0.45
(4) Percentage Classification accuracy = 48.89%
--------------------------------
LEAVING PARTICIPANT 6 OUT:
The model for participant 6 has been saved
Leaving participant 6 out
(1) Confusion matrix:
 [[11  5  0  1  1]
 [ 2 16  0  0  0]
 [ 0 17  0  0  1]
 [ 2 10  0  2  4]
 [ 1 10  0  1  6]]
(2) micro F1 score = 0.39
(3) Macro F1 score = 0.33
(4) Percentage Classification accuracy = 38.89%
--------------------------------
LEAVING PARTICIPANT 7 OUT:
The model for participant 7 has been saved
Leaving participant 7 out
(1) Confusion matrix:
 [[ 1 14  3  0  0]
 [ 0 15  0  1  2]
 [ 1 14  3  0  0]
 [ 1 10  0  5  2]
 [ 0  5  3  1  9]]
(2) micro F1 score = 0.37
(3) Macro F1 score = 0.34
(4) Percentage Classification accuracy = 36.67%
--------------------------------
LEAVING PARTICIPANT 8 OUT:
The model for participant 8 has been saved
Leaving participant 8 out
(1) Confusion matrix:
 [[ 8  0  0 10  0]
 [ 0  2  1 12  3]
 [ 1  1 11  5  0]
 [ 1  0  3 13  1]
 [ 0  0  0 13  5]]
(2) micro F1 score = 0.43
(3) Macro F1 score = 0.43
(4) Percentage Classification accuracy = 43.33%
--------------------------------
LEAVING PARTICIPANT 19 OUT:
The model for participant 19 has been saved
Leaving participant 19 out
(1) Confusion matrix:
 [[17  0  1  0  0]
 [ 9  1  5  3  0]
 [11  0  3  3  1]
 [ 1  1  0 16  0]
 [12  0  3  3  0]]
(2) micro F1 score = 0.41
(3) Macro F1 score = 0.31
(4) Percentage Classification accuracy = 41.11%
--------------------------------
LEAVING PARTICIPANT 21 OUT:
The model for participant 21 has been saved
Leaving participant 21 out
(1) Confusion matrix:
 [[ 8  6  0  0  4]
 [ 2 12  0  0  4]
 [ 0  2  0  0 16]
 [ 1  4  0  0 13]
 [ 4  8  0  0  6]]
(2) micro F1 score = 0.29
(3) Macro F1 score = 0.23
(4) Percentage Classification accuracy = 28.89%
--------------------------------
LEAVING PARTICIPANT 22 OUT:
The model for participant 22 has been saved
Leaving participant 22 out
(1) Confusion matrix:
 [[ 8  4  1  5  0]
 [ 5  6  1  4  2]
 [ 4  0  9  5  0]
 [ 1  0  0 17  0]
 [ 4  2  5  6  1]]
(2) micro F1 score = 0.46
(3) Macro F1 score = 0.41
(4) Percentage Classification accuracy = 45.56%
--------------------------------
LEAVING PARTICIPANT 23 OUT:
The model for participant 23 has been saved
Leaving participant 23 out
(1) Confusion matrix:
 [[ 0  0  0  0 18]
 [ 0  0  0  3 15]
 [ 0  1  0  4 13]
 [ 0  0  0 14  4]
 [ 0  0  0  3 15]]
(2) micro F1 score = 0.32
(3) Macro F1 score = 0.21
(4) Percentage Classification accuracy = 32.22%
--------------------------------
LEAVING PARTICIPANT 24 OUT:
The model for participant 24 has been saved
Leaving participant 24 out
(1) Confusion matrix:
 [[11  7  0  0  0]
 [ 3 14  0  0  1]
 [ 1 14  0  2  1]
 [ 0 14  0  4  0]
 [ 8  8  0  1  1]]
(2) micro F1 score = 0.33
(3) Macro F1 score = 0.27
(4) Percentage Classification accuracy = 33.33%
--------------------------------
LEAVING PARTICIPANT 25 OUT:
The model for participant 25 has been saved
Leaving participant 25 out
(1) Confusion matrix:
 [[ 5 12  0  1  0]
 [ 0 17  0  1  0]
 [ 2  8  4  4  0]
 [ 0  5  0 13  0]
 [ 1 17  0  0  0]]
(2) micro F1 score = 0.43
(3) Macro F1 score = 0.38
(4) Percentage Classification accuracy = 43.33%
--------------------------------
Using Leave One Participant Out CV (LOPOCV):
(1) Confusion matrix:
 [[262 114  34  42  52]
 [ 66 234  28  62 114]
 [ 92 126 128  70  88]
 [ 20 118  10 292  64]
 [ 74 156  36  82 156]]
(2) Average micro F1 score = 0.43
(3) Average macro F1 score = 0.37
(4) Average Percentage Classification accuracy = 42.54%
In [30]:
Linear_LOP0CV(normalised_df, model=Linear_all_features_properties(), num_folds=5, predicting_feature='property_id', learning_rate=0.005, num_epochs=150, random_state=num)
LEAVING PARTICIPANT 1 OUT:
The model for participant 1 has been saved
Leaving participant 1 out
(1) Confusion matrix:
 [[17  1  0  0  0]
 [10  6  2  0  0]
 [18  0  0  0  0]
 [ 4 11  2  0  1]
 [ 3 12  3  0  0]]
(2) micro F1 score = 0.26
(3) Macro F1 score = 0.15
(4) Percentage Classification accuracy = 25.56%
--------------------------------
LEAVING PARTICIPANT 2 OUT:
The model for participant 2 has been saved
Leaving participant 2 out
(1) Confusion matrix:
 [[ 9  1  1  6  1]
 [ 0  3  2  2 11]
 [ 6  3  9  0  0]
 [ 0  0  0 17  1]
 [ 5  0  0  3 10]]
(2) micro F1 score = 0.53
(3) Macro F1 score = 0.51
(4) Percentage Classification accuracy = 53.33%
--------------------------------
LEAVING PARTICIPANT 3 OUT:
The model for participant 3 has been saved
Leaving participant 3 out
(1) Confusion matrix:
 [[10  6  0  0  2]
 [ 0 14  0  0  4]
 [ 0  7  0  0 11]
 [ 0  0  0 14  4]
 [ 0  8  0  0 10]]
(2) micro F1 score = 0.53
(3) Macro F1 score = 0.51
(4) Percentage Classification accuracy = 53.33%
--------------------------------
LEAVING PARTICIPANT 4 OUT:
The model for participant 4 has been saved
Leaving participant 4 out
(1) Confusion matrix:
 [[13  0  5  0  0]
 [ 0  4  9  3  2]
 [ 1  1 10  3  3]
 [ 0  1  1 14  2]
 [ 0  0  5  3 10]]
(2) micro F1 score = 0.57
(3) Macro F1 score = 0.56
(4) Percentage Classification accuracy = 56.67%
--------------------------------
LEAVING PARTICIPANT 5 OUT:
The model for participant 5 has been saved
Leaving participant 5 out
(1) Confusion matrix:
 [[15  0  3  0  0]
 [ 0 13  0  0  5]
 [ 7  1  9  0  1]
 [ 0  0  0 18  0]
 [ 0  0  1  0 17]]
(2) micro F1 score = 0.8
(3) Macro F1 score = 0.79
(4) Percentage Classification accuracy = 80.0%
--------------------------------
LEAVING PARTICIPANT 6 OUT:
The model for participant 6 has been saved
Leaving participant 6 out
(1) Confusion matrix:
 [[ 2  6  6  1  3]
 [ 0  6  1  4  7]
 [ 0  8  4  2  4]
 [ 0  0  0 12  6]
 [ 0  1  0  3 14]]
(2) micro F1 score = 0.42
(3) Macro F1 score = 0.38
(4) Percentage Classification accuracy = 42.22%
--------------------------------
LEAVING PARTICIPANT 7 OUT:
The model for participant 7 has been saved
Leaving participant 7 out
(1) Confusion matrix:
 [[ 0  1 13  1  3]
 [ 0 10  3  2  3]
 [ 0  2 15  0  1]
 [ 0  3  1  8  6]
 [ 0  0  0  1 17]]
(2) micro F1 score = 0.56
(3) Macro F1 score = 0.49
(4) Percentage Classification accuracy = 55.56%
--------------------------------
LEAVING PARTICIPANT 8 OUT:
The model for participant 8 has been saved
Leaving participant 8 out
(1) Confusion matrix:
 [[14  3  0  0  1]
 [ 1 12  0  1  4]
 [ 5  2 11  0  0]
 [ 1  3  1  9  4]
 [ 0  2  0  0 16]]
(2) micro F1 score = 0.69
(3) Macro F1 score = 0.69
(4) Percentage Classification accuracy = 68.89%
--------------------------------
LEAVING PARTICIPANT 19 OUT:
The model for participant 19 has been saved
Leaving participant 19 out
(1) Confusion matrix:
 [[ 0 13  4  1  0]
 [ 0 10  3  5  0]
 [ 0  5 12  1  0]
 [ 0  0  2 16  0]
 [ 1 10  3  4  0]]
(2) micro F1 score = 0.42
(3) Macro F1 score = 0.33
(4) Percentage Classification accuracy = 42.22%
--------------------------------
LEAVING PARTICIPANT 21 OUT:
The model for participant 21 has been saved
Leaving participant 21 out
(1) Confusion matrix:
 [[14  0  1  3  0]
 [ 4  2  0  2 10]
 [ 1  0 11  4  2]
 [ 5  0  1 10  2]
 [ 7  1  1  2  7]]
(2) micro F1 score = 0.49
(3) Macro F1 score = 0.46
(4) Percentage Classification accuracy = 48.89%
--------------------------------
LEAVING PARTICIPANT 22 OUT:
The model for participant 22 has been saved
Leaving participant 22 out
(1) Confusion matrix:
 [[ 0  2  4  5  7]
 [ 0  4  1  7  6]
 [ 0  4  2  7  5]
 [ 0  0  1 17  0]
 [ 0  1  0 13  4]]
(2) micro F1 score = 0.3
(3) Macro F1 score = 0.23
(4) Percentage Classification accuracy = 30.0%
--------------------------------
LEAVING PARTICIPANT 23 OUT:
The model for participant 23 has been saved
Leaving participant 23 out
(1) Confusion matrix:
 [[15  1  1  1  0]
 [ 1  4 10  2  1]
 [ 2  0 14  1  1]
 [ 3  1  3 10  1]
 [ 8  1  5  2  2]]
(2) micro F1 score = 0.5
(3) Macro F1 score = 0.45
(4) Percentage Classification accuracy = 50.0%
--------------------------------
LEAVING PARTICIPANT 24 OUT:
The model for participant 24 has been saved
Leaving participant 24 out
(1) Confusion matrix:
 [[9 9 0 0 0]
 [0 9 1 1 7]
 [0 2 4 9 3]
 [0 1 2 8 7]
 [4 4 2 1 7]]
(2) micro F1 score = 0.41
(3) Macro F1 score = 0.41
(4) Percentage Classification accuracy = 41.11%
--------------------------------
LEAVING PARTICIPANT 25 OUT:
The model for participant 25 has been saved
Leaving participant 25 out
(1) Confusion matrix:
 [[16  1  0  1  0]
 [ 5  5  3  4  1]
 [ 1  2 12  3  0]
 [ 0  0  0 17  1]
 [ 6  3  3  4  2]]
(2) micro F1 score = 0.58
(3) Macro F1 score = 0.52
(4) Percentage Classification accuracy = 57.78%
--------------------------------
Using Leave One Participant Out CV (LOPOCV):
(1) Confusion matrix:
 [[268  88  76  38  34]
 [ 42 204  70  66 122]
 [ 82  74 226  60  62]
 [ 26  40  28 340  70]
 [ 68  86  46  72 232]]
(2) Average micro F1 score = 0.5
(3) Average macro F1 score = 0.46
(4) Average Percentage Classification accuracy = 50.4%

Run the model for ratings¶

In [32]:
Linear_LOP0CV(normalised_df, model=Linear_all_features_ratings(), num_folds=5, predicting_feature='rating_level_num', learning_rate=0.005, num_epochs=150, random_state=num)
#rating_level_num
LEAVING PARTICIPANT 1 OUT:
The model for participant 1 has been saved
Leaving participant 1 out
(1) Confusion matrix:
 [[ 9 21  0]
 [18 27  0]
 [ 3 12  0]]
(2) micro F1 score = 0.4
(3) Weighted F1 score = 0.36
(4) Percentage Classification accuracy = 40.0%
--------------------------------
LEAVING PARTICIPANT 2 OUT:
The model for participant 2 has been saved
Leaving participant 2 out
(1) Confusion matrix:
 [[25 14  0]
 [21 30  0]
 [ 0  0  0]]
(2) micro F1 score = 0.61
(3) Weighted F1 score = 0.61
(4) Percentage Classification accuracy = 61.11%
--------------------------------
LEAVING PARTICIPANT 3 OUT:
The model for participant 3 has been saved
Leaving participant 3 out
(1) Confusion matrix:
 [[32  4  0]
 [16 17  6]
 [ 1  5  9]]
(2) micro F1 score = 0.64
(3) Weighted F1 score = 0.63
(4) Percentage Classification accuracy = 64.44%
--------------------------------
LEAVING PARTICIPANT 4 OUT:
The model for participant 4 has been saved
Leaving participant 4 out
(1) Confusion matrix:
 [[13 11  0]
 [ 1 56  0]
 [ 0  9  0]]
(2) micro F1 score = 0.77
(3) Weighted F1 score = 0.72
(4) Percentage Classification accuracy = 76.67%
--------------------------------
LEAVING PARTICIPANT 5 OUT:
The model for participant 5 has been saved
Leaving participant 5 out
(1) Confusion matrix:
 [[ 8 10  0]
 [ 0 45  0]
 [ 0 25  2]]
(2) micro F1 score = 0.61
(3) Weighted F1 score = 0.52
(4) Percentage Classification accuracy = 61.11%
--------------------------------
LEAVING PARTICIPANT 6 OUT:
The model for participant 6 has been saved
Leaving participant 6 out
(1) Confusion matrix:
 [[ 6  7  5]
 [ 2 35  8]
 [ 1 20  6]]
(2) micro F1 score = 0.52
(3) Weighted F1 score = 0.49
(4) Percentage Classification accuracy = 52.22%
--------------------------------
LEAVING PARTICIPANT 7 OUT:
The model for participant 7 has been saved
Leaving participant 7 out
(1) Confusion matrix:
 [[ 9  6  0]
 [ 0 48  0]
 [ 0  9 18]]
(2) micro F1 score = 0.83
(3) Weighted F1 score = 0.83
(4) Percentage Classification accuracy = 83.33%
--------------------------------
LEAVING PARTICIPANT 8 OUT:
The model for participant 8 has been saved
Leaving participant 8 out
(1) Confusion matrix:
 [[ 8 16  3]
 [ 2 46  0]
 [ 1  9  5]]
(2) micro F1 score = 0.66
(3) Weighted F1 score = 0.61
(4) Percentage Classification accuracy = 65.56%
--------------------------------
LEAVING PARTICIPANT 19 OUT:
The model for participant 19 has been saved
Leaving participant 19 out
(1) Confusion matrix:
 [[ 0 13  5]
 [ 0 46  2]
 [ 0  0 24]]
(2) micro F1 score = 0.78
(3) Weighted F1 score = 0.69
(4) Percentage Classification accuracy = 77.78%
--------------------------------
LEAVING PARTICIPANT 21 OUT:
The model for participant 21 has been saved
Leaving participant 21 out
(1) Confusion matrix:
 [[14 13  0]
 [ 5 46  0]
 [ 0  8  4]]
(2) micro F1 score = 0.71
(3) Weighted F1 score = 0.69
(4) Percentage Classification accuracy = 71.11%
--------------------------------
LEAVING PARTICIPANT 22 OUT:
The model for participant 22 has been saved
Leaving participant 22 out
(1) Confusion matrix:
 [[ 0  1  8]
 [ 0  7  8]
 [ 0  4 62]]
(2) micro F1 score = 0.77
(3) Weighted F1 score = 0.72
(4) Percentage Classification accuracy = 76.67%
--------------------------------
LEAVING PARTICIPANT 23 OUT:
The model for participant 23 has been saved
Leaving participant 23 out
(1) Confusion matrix:
 [[ 3  6  3]
 [ 0 41  1]
 [ 0  9 27]]
(2) micro F1 score = 0.79
(3) Weighted F1 score = 0.77
(4) Percentage Classification accuracy = 78.89%
--------------------------------
LEAVING PARTICIPANT 24 OUT:
The model for participant 24 has been saved
Leaving participant 24 out
(1) Confusion matrix:
 [[ 0  5  4]
 [ 0 57  0]
 [ 0  7 17]]
(2) micro F1 score = 0.82
(3) Weighted F1 score = 0.77
(4) Percentage Classification accuracy = 82.22%
--------------------------------
LEAVING PARTICIPANT 25 OUT:
The model for participant 25 has been saved
Leaving participant 25 out
(1) Confusion matrix:
 [[ 0 16  2]
 [ 0 48  3]
 [ 0  3 18]]
(2) micro F1 score = 0.73
(3) Weighted F1 score = 0.65
(4) Percentage Classification accuracy = 73.33%
--------------------------------
Using Leave One Participant Out CV (LOPOCV):
(1) Confusion matrix:
 [[ 254  286   60]
 [ 130 1098   56]
 [  12  240  384]]
(2) Average micro F1 score = 0.69
(3) Average weighted F1 score = 0.65
(4) Average Percentage Classification accuracy = 68.89%

Model 2 - Linear model using only the emg data (48 features)¶

In [33]:
complete_emg = normalised_df.iloc[:,:59]

Create the model¶

In [140]:
class Linear_emg_features_properties(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(48, 25)
        self.fc2 = nn.Linear(25, 10)
        self.fc3 = nn.Linear(10, 5)        
           
    def forward(self, x): #, x2
        #print(x.shape)
        x = F.tanh(self.fc1(x))
        x = F.tanh(self.fc2(x))
        x = F.softmax(self.fc3(x), dim=1)
        return x

class Linear_emg_features_ratings(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(48+5, 25)
        self.fc2 = nn.Linear(25, 10)
        self.fc3 = nn.Linear(10, 3)        

    def forward(self, x): #, x2
        #print(x.shape)
        x = F.tanh(self.fc1(x))
        x = F.tanh(self.fc2(x))
        x = F.softmax(self.fc3(x), dim=1)
        return x

Run the model for properties¶

In [142]:
Linear_LOP0CV(complete_emg, model=Linear_emg_features_properties(), num_folds=5, predicting_feature='property_id', learning_rate=0.005, num_epochs=150, random_state=num)
LEAVING PARTICIPANT 1 OUT:
The model for participant 1 has been saved
Leaving participant 1 out
(1) Confusion matrix:
 [[16  0  2  0  0]
 [12  0  1  0  5]
 [18  0  0  0  0]
 [ 7  0  1  2  8]
 [ 7  0  2  0  9]]
(2) micro F1 score = 0.3
(3) Macro F1 score = 0.21
(4) Percentage Classification accuracy = 30.0%
--------------------------------
LEAVING PARTICIPANT 2 OUT:
The model for participant 2 has been saved
Leaving participant 2 out
(1) Confusion matrix:
 [[ 0  8  1  7  2]
 [ 0  8  0 10  0]
 [ 0  1 17  0  0]
 [ 0  0  0 17  1]
 [ 0  3  1 10  4]]
(2) micro F1 score = 0.51
(3) Macro F1 score = 0.44
(4) Percentage Classification accuracy = 51.11%
--------------------------------
LEAVING PARTICIPANT 3 OUT:
The model for participant 3 has been saved
Leaving participant 3 out
(1) Confusion matrix:
 [[17  0  1  0  0]
 [ 0 17  0  0  1]
 [ 1  1 15  0  1]
 [ 0  3  0 14  1]
 [ 0  6  1  0 11]]
(2) micro F1 score = 0.82
(3) Macro F1 score = 0.82
(4) Percentage Classification accuracy = 82.22%
--------------------------------
LEAVING PARTICIPANT 4 OUT:
The model for participant 4 has been saved
Leaving participant 4 out
(1) Confusion matrix:
 [[12  5  0  0  1]
 [ 0 13  0  4  1]
 [ 1  6  9  2  0]
 [ 0  2  1 15  0]
 [ 1  1  0  3 13]]
(2) micro F1 score = 0.69
(3) Macro F1 score = 0.69
(4) Percentage Classification accuracy = 68.89%
--------------------------------
LEAVING PARTICIPANT 5 OUT:
The model for participant 5 has been saved
Leaving participant 5 out
(1) Confusion matrix:
 [[16  0  2  0  0]
 [ 0 16  2  0  0]
 [ 5  3  9  1  0]
 [ 0  0  0 17  1]
 [ 0  2  1  0 15]]
(2) micro F1 score = 0.81
(3) Macro F1 score = 0.81
(4) Percentage Classification accuracy = 81.11%
--------------------------------
LEAVING PARTICIPANT 6 OUT:
The model for participant 6 has been saved
Leaving participant 6 out
(1) Confusion matrix:
 [[17  0  0  1  0]
 [ 2 13  1  0  2]
 [ 2  0 14  0  2]
 [ 1  2  1 12  2]
 [ 0  4  0  1 13]]
(2) micro F1 score = 0.77
(3) Macro F1 score = 0.77
(4) Percentage Classification accuracy = 76.67%
--------------------------------
LEAVING PARTICIPANT 7 OUT:
The model for participant 7 has been saved
Leaving participant 7 out
(1) Confusion matrix:
 [[17  0  0  0  1]
 [ 4 10  1  0  3]
 [ 4  2 12  0  0]
 [ 4  0  0  8  6]
 [ 2  0  0  1 15]]
(2) micro F1 score = 0.69
(3) Macro F1 score = 0.69
(4) Percentage Classification accuracy = 68.89%
--------------------------------
LEAVING PARTICIPANT 8 OUT:
The model for participant 8 has been saved
Leaving participant 8 out
(1) Confusion matrix:
 [[16  1  1  0  0]
 [ 1 15  2  0  0]
 [ 1  5 12  0  0]
 [ 2  3  0 11  2]
 [ 3  2  1  0 12]]
(2) micro F1 score = 0.73
(3) Macro F1 score = 0.74
(4) Percentage Classification accuracy = 73.33%
--------------------------------
LEAVING PARTICIPANT 19 OUT:
The model for participant 19 has been saved
Leaving participant 19 out
(1) Confusion matrix:
 [[16  0  2  0  0]
 [ 3  5  9  1  0]
 [ 4  0 12  2  0]
 [ 0  0  4 14  0]
 [11  1  0  0  6]]
(2) micro F1 score = 0.59
(3) Macro F1 score = 0.57
(4) Percentage Classification accuracy = 58.89%
--------------------------------
LEAVING PARTICIPANT 21 OUT:
The model for participant 21 has been saved
Leaving participant 21 out
(1) Confusion matrix:
 [[16  1  1  0  0]
 [ 5  9  2  2  0]
 [ 2  2 12  2  0]
 [ 4  0  5  9  0]
 [ 5  8  1  2  2]]
(2) micro F1 score = 0.53
(3) Macro F1 score = 0.49
(4) Percentage Classification accuracy = 53.33%
--------------------------------
LEAVING PARTICIPANT 22 OUT:
The model for participant 22 has been saved
Leaving participant 22 out
(1) Confusion matrix:
 [[11  2  1  1  3]
 [ 1 14  1  2  0]
 [ 0  4  9  2  3]
 [ 0  2  3 12  1]
 [ 3  3  5  3  4]]
(2) micro F1 score = 0.56
(3) Macro F1 score = 0.54
(4) Percentage Classification accuracy = 55.56%
--------------------------------
LEAVING PARTICIPANT 23 OUT:
The model for participant 23 has been saved
Leaving participant 23 out
(1) Confusion matrix:
 [[16  0  0  2  0]
 [ 1 16  1  0  0]
 [ 2  4 10  2  0]
 [ 0  2  1 15  0]
 [ 8  6  0  4  0]]
(2) micro F1 score = 0.63
(3) Macro F1 score = 0.56
(4) Percentage Classification accuracy = 63.33%
--------------------------------
LEAVING PARTICIPANT 24 OUT:
The model for participant 24 has been saved
Leaving participant 24 out
(1) Confusion matrix:
 [[16  0  2  0  0]
 [ 1 15  2  0  0]
 [ 0  2 12  4  0]
 [ 1  1  1 15  0]
 [ 9  1  4  2  2]]
(2) micro F1 score = 0.67
(3) Macro F1 score = 0.62
(4) Percentage Classification accuracy = 66.67%
--------------------------------
LEAVING PARTICIPANT 25 OUT:
The model for participant 25 has been saved
Leaving participant 25 out
(1) Confusion matrix:
 [[13  2  2  0  1]
 [ 0 13  1  4  0]
 [ 3  1 13  1  0]
 [ 0  0  1 16  1]
 [ 2  6  4  2  4]]
(2) micro F1 score = 0.66
(3) Macro F1 score = 0.63
(4) Percentage Classification accuracy = 65.56%
--------------------------------
Using Leave One Participant Out CV (LOPOCV):
(1) Confusion matrix:
 [[398  38  30  22  16]
 [ 60 328  46  46  24]
 [ 86  62 312  32  12]
 [ 38  30  36 354  46]
 [102  86  40  56 220]]
(2) Average micro F1 score = 0.64
(3) Average macro F1 score = 0.61
(4) Average Percentage Classification accuracy = 63.97%

Run the model for ratings¶

In [141]:
Linear_LOP0CV(complete_emg, model=Linear_emg_features_ratings(), num_folds=5, predicting_feature='rating_level_num', learning_rate=0.0001, num_epochs=150, random_state=num)
     
LEAVING PARTICIPANT 1 OUT:
The model for participant 1 has been saved
Leaving participant 1 out
(1) Confusion matrix:
 [[ 0 29  1]
 [ 0 45  0]
 [ 0 15  0]]
(2) micro F1 score = 0.5
(3) Weighted F1 score = 0.34
(4) Percentage Classification accuracy = 50.0%
--------------------------------
LEAVING PARTICIPANT 2 OUT:
The model for participant 2 has been saved
Leaving participant 2 out
(1) Confusion matrix:
 [[ 0 39  0]
 [ 0 51  0]
 [ 0  0  0]]
(2) micro F1 score = 0.57
(3) Weighted F1 score = 0.41
(4) Percentage Classification accuracy = 56.67%
--------------------------------
LEAVING PARTICIPANT 3 OUT:
The model for participant 3 has been saved
Leaving participant 3 out
(1) Confusion matrix:
 [[12 24  0]
 [ 6 32  1]
 [ 4  8  3]]
(2) micro F1 score = 0.52
(3) Weighted F1 score = 0.49
(4) Percentage Classification accuracy = 52.22%
--------------------------------
LEAVING PARTICIPANT 4 OUT:
The model for participant 4 has been saved
Leaving participant 4 out
(1) Confusion matrix:
 [[ 7 17  0]
 [ 7 50  0]
 [ 0  9  0]]
(2) micro F1 score = 0.63
(3) Weighted F1 score = 0.57
(4) Percentage Classification accuracy = 63.33%
--------------------------------
LEAVING PARTICIPANT 5 OUT:
The model for participant 5 has been saved
Leaving participant 5 out
(1) Confusion matrix:
 [[ 8 10  0]
 [ 1 44  0]
 [ 0 27  0]]
(2) micro F1 score = 0.58
(3) Weighted F1 score = 0.47
(4) Percentage Classification accuracy = 57.78%
--------------------------------
LEAVING PARTICIPANT 6 OUT:
The model for participant 6 has been saved
Leaving participant 6 out
(1) Confusion matrix:
 [[ 2 16  0]
 [ 0 45  0]
 [ 1 26  0]]
(2) micro F1 score = 0.52
(3) Weighted F1 score = 0.38
(4) Percentage Classification accuracy = 52.22%
--------------------------------
LEAVING PARTICIPANT 7 OUT:
The model for participant 7 has been saved
Leaving participant 7 out
(1) Confusion matrix:
 [[11  4  0]
 [ 0 44  4]
 [ 0 10 17]]
(2) micro F1 score = 0.8
(3) Weighted F1 score = 0.8
(4) Percentage Classification accuracy = 80.0%
--------------------------------
LEAVING PARTICIPANT 8 OUT:
The model for participant 8 has been saved
Leaving participant 8 out
(1) Confusion matrix:
 [[ 7 17  3]
 [ 4 42  2]
 [ 0  8  7]]
(2) micro F1 score = 0.62
(3) Weighted F1 score = 0.59
(4) Percentage Classification accuracy = 62.22%
--------------------------------
LEAVING PARTICIPANT 19 OUT:
The model for participant 19 has been saved
Leaving participant 19 out
(1) Confusion matrix:
 [[ 2 14  2]
 [ 0 47  1]
 [ 0 12 12]]
(2) micro F1 score = 0.68
(3) Weighted F1 score = 0.62
(4) Percentage Classification accuracy = 67.78%
--------------------------------
LEAVING PARTICIPANT 21 OUT:
The model for participant 21 has been saved
Leaving participant 21 out
(1) Confusion matrix:
 [[17 10  0]
 [ 8 43  0]
 [ 6  6  0]]
(2) micro F1 score = 0.67
(3) Weighted F1 score = 0.62
(4) Percentage Classification accuracy = 66.67%
--------------------------------
LEAVING PARTICIPANT 22 OUT:
The model for participant 22 has been saved
Leaving participant 22 out
(1) Confusion matrix:
 [[ 3  1  5]
 [ 0  1 14]
 [ 0  0 66]]
(2) micro F1 score = 0.78
(3) Weighted F1 score = 0.71
(4) Percentage Classification accuracy = 77.78%
--------------------------------
LEAVING PARTICIPANT 23 OUT:
The model for participant 23 has been saved
Leaving participant 23 out
(1) Confusion matrix:
 [[ 0  4  8]
 [ 0 27 15]
 [ 0  9 27]]
(2) micro F1 score = 0.6
(3) Weighted F1 score = 0.56
(4) Percentage Classification accuracy = 60.0%
--------------------------------
LEAVING PARTICIPANT 24 OUT:
The model for participant 24 has been saved
Leaving participant 24 out
(1) Confusion matrix:
 [[ 0  3  6]
 [ 0 57  0]
 [ 0  3 21]]
(2) micro F1 score = 0.87
(3) Weighted F1 score = 0.82
(4) Percentage Classification accuracy = 86.67%
--------------------------------
LEAVING PARTICIPANT 25 OUT:
The model for participant 25 has been saved
Leaving participant 25 out
(1) Confusion matrix:
 [[ 0 15  3]
 [ 1 50  0]
 [ 0 12  9]]
(2) micro F1 score = 0.66
(3) Weighted F1 score = 0.57
(4) Percentage Classification accuracy = 65.56%
--------------------------------
Using Leave One Participant Out CV (LOPOCV):
(1) Confusion matrix:
 [[ 138  406   56]
 [  54 1156   74]
 [  22  290  324]]
(2) Average micro F1 score = 0.64
(3) Average weighted F1 score = 0.57
(4) Average Percentage Classification accuracy = 64.21%

Model 3 - LSTM + fully connected layers using all 180 features¶

complete_emg = normalised_df.iloc[:,:59] hand0_emg = normalised_df.iloc[:,35:59] hand0_emg.head()

In [113]:
# Obtain features for each hand
hand1_emg = normalised_df.iloc[:,35:59]

hand0_acc = normalised_df.iloc[:,59:86]
hand1_acc = normalised_df.iloc[:,86:113]

hand0_qua = normalised_df.iloc[:,113:152]
hand1_qua = normalised_df.iloc[:,152:]

# Combine the data to ceate a df for each hand
emg_0 = normalised_df.iloc[:,:35]
hand_0 = pd.concat([emg_0, hand0_acc, hand0_qua], axis=1)
hand_1 = pd.concat([df_info, hand1_emg, hand1_acc, hand1_qua], axis=1)

Create the model¶

In [114]:
class LSTM_all_features_properties(nn.Module):
    def __init__(self):
        super().__init__()
        self.rnn = nn.LSTM(90, 40, 1, batch_first=True)
        self.fc1 = nn.Linear(3 * 40 * 2, 20)
        self.fc2 = nn.Linear(20, 10)
        self.fc3 = nn.Linear(10, 5)
          
    def forward(self, x1, x2): #, x2
        x1, (hn, cn) = self.rnn(x1) #, (self.h0, self.c0)
        x1 = F.tanh(x1)
        x2, (hm, cm) = self.rnn(x2) # (self.h0, self.c0)
        x2 = F.tanh(x2)
        
        x = torch.cat((x1, x2), 2)
        
        x = torch.flatten(x, 1) # flatten all dimensions except batch
        x = F.tanh(self.fc1(x))
        x = F.tanh(self.fc2(x))
        x = F.softmax(self.fc3(x), dim=1)
        return x
    
class LSTM_all_features_ratings(nn.Module):
    def __init__(self):
        super().__init__()
        self.rnn = nn.LSTM(90+5, 40, 1, batch_first=True)
        self.fc1 = nn.Linear(3 * 40 * 2, 20)
        self.fc2 = nn.Linear(20, 10)
        self.fc3 = nn.Linear(10, 3)
          
    def forward(self, x1, x2): #, x2
        x1, (hn, cn) = self.rnn(x1) #, (self.h0, self.c0)
        x1 = F.tanh(x1)
        x2, (hm, cm) = self.rnn(x2) # (self.h0, self.c0)
        x2 = F.tanh(x2)
        
        x = torch.cat((x1, x2), 2)
        
        x = torch.flatten(x, 1) # flatten all dimensions except batch
        x = F.tanh(self.fc1(x))
        x = F.tanh(self.fc2(x))
        x = F.softmax(self.fc3(x), dim=1)
        return x
    
In [118]:
def find_best_model_for_3d_X(train_dataloader, val_dataloader, learning_rate, num_epochs, model):

    # Model
    train_model = model

    # Loss and Optimiser
    criterion = torch.nn.CrossEntropyLoss()
    optimizer = optim.SGD(train_model.parameters(), lr=learning_rate, momentum=0.7)

    best_avg_loss = np.inf
    best_model = None
    #best_model_epoch_num = np.inf
    train_loss_lst = []
    val_loss_lst = []
    avg_loss_lst = []

    for epoch in range(num_epochs):  # loop over the dataset multiple times

        #Set the model in training mode
        train_model.train()

        # Initialise the total training and validation loss
        epoch_train_loss = 0
        epoch_val_loss = 0
        avg_loss = 0

        #running_loss = 0.0
        for i, train_data in enumerate(train_dataloader, 0):
            #print(len(train_data))

            # get the inputs; data is a list of [input1, input2, label]
            train_input1, train_input2, train_labels = train_data #train_input2, 

            #train_labels = train_labels.type(torch.LongTensor)

            # zero the parameter gradients
            optimizer.zero_grad()

            # forward + backward + optimize
            train_preds = train_model(train_input1, train_input2)  
            #print(train_labels)#

            train_loss = criterion(train_preds, train_labels)
            train_loss.backward()
            optimizer.step()

            # Update training loss
            epoch_train_loss += train_loss.item()

        # Switch off auto grad for evaluation
        with torch.no_grad():

            # Set the model in evaluation mode
            train_model.eval()

            for j, val_data in enumerate(val_dataloader, 0):
               # print(len(val_data))
            # get the inputs; data is a list of [input1, input2, label]
                val_input1, val_input2, val_labels = val_data # val_input2, 

                #val_labels = val_labels.type(torch.LongTensor)

                val_preds = train_model(val_input1, val_input2) #, val_input2

                # Update validation loss
                val_loss = criterion(val_preds, val_labels)

                epoch_val_loss += val_loss.item()
     
        avg_training_loss = epoch_train_loss / len(train_dataloader) #count_train
        avg_validation_loss = epoch_val_loss / len(val_dataloader) #count_val
        avg_loss = (avg_training_loss + avg_validation_loss) / 2
        
        train_loss_lst.append(avg_training_loss)
        val_loss_lst.append(avg_validation_loss)
        avg_loss_lst.append(avg_loss)
         
        #print(f'epoch {epoch+1}: train loss = {round(avg_training_loss,3)}, val loss = {round(avg_validation_loss,3)}, average loss = {round(avg_loss,3)}')

        if avg_loss < best_avg_loss:
            best_avg_loss = avg_loss
            best_model = train_model.state_dict()

    return best_avg_loss, best_model, train_loss_lst, val_loss_lst, avg_loss_lst   #, avg_loss_lst, 
In [119]:
# Original
def LSTM_LOP0CV(data_0, data_1, model, num_folds=5, predicting_feature='property_id', learning_rate=0.01, num_epochs=10, random_state=num): #, num_inner_folds=5
    # Set fixed random number seed
    torch.manual_seed(num)
        
    total_conf_mat = 0
    micro_f1_lst = []
    acc_lst = []
    if predicting_feature == 'property_id':
        macro_f1_lst = []
    elif predicting_feature == 'rating_level_num':
        weighted_f1_lst = [] 
        
        data0_add = create_y_train_for_2d_X(data_0, predicting_feature = 'property_id', output_as_tensor='No')
        data0_add_pd = pd.DataFrame(data0_add, columns = ['smoothness','thickness','warmth', 'flexibility', 'softness'])
        data_0 = pd.concat([data_0.reset_index(drop=True), data0_add_pd.reset_index(drop=True)], axis=1)
        data1_add = create_y_train_for_2d_X(data_1, predicting_feature = 'property_id', output_as_tensor='No')
        data1_add_pd = pd.DataFrame(data1_add, columns = ['smoothness','thickness','warmth', 'flexibility', 'softness'])
        data_1 = pd.concat([data_1.reset_index(drop=True), data1_add_pd.reset_index(drop=True)], axis=1)
    
    for participant in sorted(data_0.participant_id.unique()): # # #:lst: #
        print(f'LEAVING PARTICIPANT {participant} OUT:')
        
        # Split the data into training and testing
        training_data_0 = data_0[data_0.participant_id != participant] 
        training_data_1 = data_1[data_1.participant_id != participant] 
        testing_data_0 = data_0[data_0.participant_id == participant] 
        testing_data_1 = data_1[data_1.participant_id == participant] 

        # Data preparation
        X_train_0 = create_X_3d(training_data_0, 11)
        X_train_1 = create_X_3d(training_data_1, 11) 
        X_test_0 = create_X_3d(testing_data_0, 11) 
        X_test_1 = create_X_3d(testing_data_1, 11)           
        y_train = create_y_train_for_3d_X(training_data_0, predicting_feature = predicting_feature)
        y_test = create_y_test_for_3d_X(testing_data_0, predicting_feature = predicting_feature)        
 

        #print(X_train_0.shape)
        #print(X_train_1.shape)
        #print(y_train.shape)
        #print(X_test_0.shape)
        #print(X_test_1.shape)
        #print(y_test.shape)
 
        # Create the datasets and dataloaders
        train_dataset = TensorDataset(X_train_0, X_train_1, y_train) 
        
        test_dataset = TensorDataset(X_test_0, X_test_1, y_test)
        test_dataloader = torch.utils.data.DataLoader(test_dataset, shuffle=True, batch_size=30) # num_workers=2,       
            
        # Configure the cross-validation procedure
        cv_inner = KFold(n_splits=num_folds, shuffle=True, random_state=num)
                
        min_avg_loss_subject = np.inf
        best_model_subject = None
        
        best_train_loss_lst = None
        best_val_loss_lst = None
        best_avg_loss_lst = None
        best_fold = np.inf

        for fold, (train_ids, val_ids) in enumerate(cv_inner.split(train_dataset)):
            #print(f'FOLD {fold+1}:')
                       
            # Sample elements randomly from a given list of ids, no replacement.
            train_subsampler = torch.utils.data.SubsetRandomSampler(train_ids) # The ids are the same for both
            val_subsampler = torch.utils.data.SubsetRandomSampler(val_ids)

            # Define data loaders for training and testing data in this fold
            train_dataloader = torch.utils.data.DataLoader(train_dataset, sampler=train_subsampler) #, batch_size=100
            val_dataloader = torch.utils.data.DataLoader(train_dataset, sampler=val_subsampler) #, batch_size=20        

            avg_loss_fold, best_model_fold, fold_train_loss_lst, fold_val_loss_lst, fold_avg_loss_lst = find_best_model_for_3d_X(train_dataloader, val_dataloader, learning_rate, num_epochs, model)
                           
            if avg_loss_fold < min_avg_loss_subject:
                min_avg_loss_subject = avg_loss_fold
                best_model_subject = best_model_fold
                best_train_loss_lst = fold_train_loss_lst
                best_val_loss_lst = fold_val_loss_lst
                best_avg_loss_lst = fold_avg_loss_lst
                best_fold = fold+1

        fig = plt.figure(f"{participant}")                  
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_train_loss_lst)
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_val_loss_lst)
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_avg_loss_lst)
        plt.title(f"Loss when participant {participant} is left out for fold {best_fold} (lr={learning_rate}, num_epochs ={num_epochs})")
        plt.legend(['train loss', 'val loss', 'avg_loss'])

        # save trained model 
        name = 'model_participant_'+str(participant)+'.pt'
        torch.save(best_model_subject, name)
        print(f'The model for participant {participant} has been saved')
        
        test_model = model
        test_model.load_state_dict(torch.load(name))

        dataiter = iter(test_dataloader) 
        test_input1, test_input2, test_labels = dataiter.next() 
    
        test_preds = test_model(test_input1, test_input2) 
        
        test_preds_np = test_preds.detach().numpy()
        test_predicted_np = np.argmax(test_preds_np, axis = 1)
        
        test_labels_np = test_labels.numpy()    
        
        if predicting_feature == 'property_id':
            conf_mat = confusion_matrix(test_labels_np, test_predicted_np, labels=[0, 1, 2, 3, 4])
            macro_f1_score = f1_score(test_labels_np, test_predicted_np, average='macro') 
            macro_f1_lst.append(macro_f1_score) 
        elif predicting_feature == 'rating_level_num':
            conf_mat = confusion_matrix(test_labels_np, test_predicted_np, labels=[0,1,2])
            weighted_f1_score = f1_score(test_labels_np, test_predicted_np, average='weighted') 
            weighted_f1_lst.append(weighted_f1_score)
            
        total_conf_mat += conf_mat
        micro_f1_score = f1_score(test_labels_np, test_predicted_np, average='micro')  
        micro_f1_lst.append(micro_f1_score)
        acc = accuracy_score(test_labels_np, test_predicted_np)
        acc_lst.append(acc)


        print(f"Leaving participant {participant} out")
        print("(1) Confusion matrix:\n", conf_mat)
        print(f"(2) micro F1 score = {round(micro_f1_score,2)}")
        if predicting_feature == 'property_id':
            print(f"(3) Macro F1 score = {round(macro_f1_score,2)}")
        elif predicting_feature == 'rating_level_num':
            print(f"(3) Weighted F1 score = {round(weighted_f1_score,2)}")            
        print(f"(4) Percentage Classification accuracy = {round(acc*100,2)}%")
        
        total_conf_mat += conf_mat 
        micro_f1_lst.append(micro_f1_score)
        acc_lst.append(acc)
        print('--------------------------------')
        
    avg_micro_f1_score = sum(micro_f1_lst) / len(micro_f1_lst)
    if predicting_feature == 'property_id':
        avg_macro_f1_score = sum(macro_f1_lst) / len(macro_f1_lst)  
    elif predicting_feature == 'rating_level_num':
        avg_weighted_f1_score = sum(weighted_f1_lst) / len(weighted_f1_lst)             
    avg_acc = sum(acc_lst) / len(acc_lst)   
    
    print(f'Using Leave One Participant Out CV (LOPOCV):') 
    print("(1) Confusion matrix:\n", total_conf_mat)
    print(f"(2) Average micro F1 score = {round(avg_micro_f1_score,2)}")
    if predicting_feature == 'property_id':
        print(f"(3) Average macro F1 score = {round(avg_macro_f1_score,2)}")
    elif predicting_feature == 'rating_level_num':
        print(f"(3) Average weighted F1 score = {round(avg_weighted_f1_score,2)}")      
    print(f"(4) Average Percentage Classification accuracy = {round(avg_acc*100,2)}%")
            

Run the model for properties¶

In [120]:
LSTM_LOP0CV(hand_0, hand_1, model=LSTM_all_features_properties(), num_folds=5, predicting_feature='property_id', learning_rate=0.085, num_epochs=50, random_state=num) #, num_inner_folds=5
LEAVING PARTICIPANT 1 OUT:
The model for participant 1 has been saved
Leaving participant 1 out
(1) Confusion matrix:
 [[0 0 0 6 0]
 [0 0 0 6 0]
 [1 0 0 5 0]
 [0 0 0 6 0]
 [0 0 0 6 0]]
(2) micro F1 score = 0.2
(3) Macro F1 score = 0.07
(4) Percentage Classification accuracy = 20.0%
--------------------------------
LEAVING PARTICIPANT 2 OUT:
The model for participant 2 has been saved
Leaving participant 2 out
(1) Confusion matrix:
 [[0 6 0 0 0]
 [0 6 0 0 0]
 [0 6 0 0 0]
 [0 6 0 0 0]
 [0 6 0 0 0]]
(2) micro F1 score = 0.2
(3) Macro F1 score = 0.07
(4) Percentage Classification accuracy = 20.0%
--------------------------------
LEAVING PARTICIPANT 3 OUT:
The model for participant 3 has been saved
Leaving participant 3 out
(1) Confusion matrix:
 [[0 0 6 0 0]
 [0 0 6 0 0]
 [0 0 6 0 0]
 [0 0 6 0 0]
 [0 0 6 0 0]]
(2) micro F1 score = 0.2
(3) Macro F1 score = 0.07
(4) Percentage Classification accuracy = 20.0%
--------------------------------
LEAVING PARTICIPANT 4 OUT:
The model for participant 4 has been saved
Leaving participant 4 out
(1) Confusion matrix:
 [[0 0 0 0 6]
 [0 0 0 0 6]
 [0 0 0 0 6]
 [0 0 0 0 6]
 [0 0 0 0 6]]
(2) micro F1 score = 0.2
(3) Macro F1 score = 0.07
(4) Percentage Classification accuracy = 20.0%
--------------------------------
LEAVING PARTICIPANT 5 OUT:
The model for participant 5 has been saved
Leaving participant 5 out
(1) Confusion matrix:
 [[0 0 0 6 0]
 [0 0 0 6 0]
 [0 0 0 6 0]
 [0 0 0 6 0]
 [0 0 0 6 0]]
(2) micro F1 score = 0.2
(3) Macro F1 score = 0.07
(4) Percentage Classification accuracy = 20.0%
--------------------------------
LEAVING PARTICIPANT 6 OUT:
The model for participant 6 has been saved
Leaving participant 6 out
(1) Confusion matrix:
 [[0 0 6 0 0]
 [0 0 6 0 0]
 [0 0 6 0 0]
 [0 0 6 0 0]
 [0 0 6 0 0]]
(2) micro F1 score = 0.2
(3) Macro F1 score = 0.07
(4) Percentage Classification accuracy = 20.0%
--------------------------------
LEAVING PARTICIPANT 7 OUT:
The model for participant 7 has been saved
Leaving participant 7 out
(1) Confusion matrix:
 [[0 0 0 6 0]
 [0 0 0 6 0]
 [0 0 0 6 0]
 [0 0 0 6 0]
 [0 0 0 6 0]]
(2) micro F1 score = 0.2
(3) Macro F1 score = 0.07
(4) Percentage Classification accuracy = 20.0%
--------------------------------
LEAVING PARTICIPANT 8 OUT:
The model for participant 8 has been saved
Leaving participant 8 out
(1) Confusion matrix:
 [[1 0 0 0 5]
 [0 0 0 0 6]
 [0 0 0 0 6]
 [0 0 0 0 6]
 [0 0 0 0 6]]
(2) micro F1 score = 0.23
(3) Macro F1 score = 0.13
(4) Percentage Classification accuracy = 23.33%
--------------------------------
LEAVING PARTICIPANT 19 OUT:
The model for participant 19 has been saved
Leaving participant 19 out
(1) Confusion matrix:
 [[0 0 6 0 0]
 [0 0 6 0 0]
 [0 0 6 0 0]
 [0 0 6 0 0]
 [0 0 6 0 0]]
(2) micro F1 score = 0.2
(3) Macro F1 score = 0.07
(4) Percentage Classification accuracy = 20.0%
--------------------------------
LEAVING PARTICIPANT 21 OUT:
The model for participant 21 has been saved
Leaving participant 21 out
(1) Confusion matrix:
 [[6 0 0 0 0]
 [6 0 0 0 0]
 [6 0 0 0 0]
 [6 0 0 0 0]
 [6 0 0 0 0]]
(2) micro F1 score = 0.2
(3) Macro F1 score = 0.07
(4) Percentage Classification accuracy = 20.0%
--------------------------------
LEAVING PARTICIPANT 22 OUT:
The model for participant 22 has been saved
Leaving participant 22 out
(1) Confusion matrix:
 [[0 0 6 0 0]
 [0 0 6 0 0]
 [0 0 6 0 0]
 [0 0 6 0 0]
 [0 0 6 0 0]]
(2) micro F1 score = 0.2
(3) Macro F1 score = 0.07
(4) Percentage Classification accuracy = 20.0%
--------------------------------
LEAVING PARTICIPANT 23 OUT:
The model for participant 23 has been saved
Leaving participant 23 out
(1) Confusion matrix:
 [[0 0 0 6 0]
 [0 0 0 6 0]
 [0 0 0 6 0]
 [0 0 0 6 0]
 [0 0 0 6 0]]
(2) micro F1 score = 0.2
(3) Macro F1 score = 0.07
(4) Percentage Classification accuracy = 20.0%
--------------------------------
LEAVING PARTICIPANT 24 OUT:
The model for participant 24 has been saved
Leaving participant 24 out
(1) Confusion matrix:
 [[1 5 0 0 0]
 [0 6 0 0 0]
 [0 6 0 0 0]
 [0 6 0 0 0]
 [0 6 0 0 0]]
(2) micro F1 score = 0.23
(3) Macro F1 score = 0.13
(4) Percentage Classification accuracy = 23.33%
--------------------------------
LEAVING PARTICIPANT 25 OUT:
The model for participant 25 has been saved
Leaving participant 25 out
(1) Confusion matrix:
 [[0 0 0 0 6]
 [0 0 0 0 6]
 [0 0 0 0 6]
 [0 0 0 0 6]
 [0 0 0 0 6]]
(2) micro F1 score = 0.2
(3) Macro F1 score = 0.07
(4) Percentage Classification accuracy = 20.0%
--------------------------------
Using Leave One Participant Out CV (LOPOCV):
(1) Confusion matrix:
 [[16 22 48 48 34]
 [12 24 48 48 36]
 [14 24 48 46 36]
 [12 24 48 48 36]
 [12 24 48 48 36]]
(2) Average micro F1 score = 0.2
(3) Average macro F1 score = 0.08
(4) Average Percentage Classification accuracy = 20.48%

Run the model for ratings¶

In [121]:
LSTM_LOP0CV(hand_0, hand_1, model=LSTM_all_features_ratings(), num_folds=5, predicting_feature='rating_level_num', learning_rate=0.005, num_epochs=50, random_state=num) #, num_inner_folds=5
LEAVING PARTICIPANT 1 OUT:
The model for participant 1 has been saved
Leaving participant 1 out
(1) Confusion matrix:
 [[5 5 0]
 [7 8 0]
 [2 3 0]]
(2) micro F1 score = 0.43
(3) Weighted F1 score = 0.4
(4) Percentage Classification accuracy = 43.33%
--------------------------------
LEAVING PARTICIPANT 2 OUT:
The model for participant 2 has been saved
Leaving participant 2 out
(1) Confusion matrix:
 [[ 4  9  0]
 [ 0 17  0]
 [ 0  0  0]]
(2) micro F1 score = 0.7
(3) Weighted F1 score = 0.65
(4) Percentage Classification accuracy = 70.0%
--------------------------------
LEAVING PARTICIPANT 3 OUT:
The model for participant 3 has been saved
Leaving participant 3 out
(1) Confusion matrix:
 [[11  1  0]
 [ 2 11  0]
 [ 2  2  1]]
(2) micro F1 score = 0.77
(3) Weighted F1 score = 0.73
(4) Percentage Classification accuracy = 76.67%
--------------------------------
LEAVING PARTICIPANT 4 OUT:
The model for participant 4 has been saved
Leaving participant 4 out
(1) Confusion matrix:
 [[ 6  2  0]
 [ 0 19  0]
 [ 1  2  0]]
(2) micro F1 score = 0.83
(3) Weighted F1 score = 0.79
(4) Percentage Classification accuracy = 83.33%
--------------------------------
LEAVING PARTICIPANT 5 OUT:
The model for participant 5 has been saved
Leaving participant 5 out
(1) Confusion matrix:
 [[ 4  2  0]
 [ 0 15  0]
 [ 5  4  0]]
(2) micro F1 score = 0.63
(3) Weighted F1 score = 0.52
(4) Percentage Classification accuracy = 63.33%
--------------------------------
LEAVING PARTICIPANT 6 OUT:
The model for participant 6 has been saved
Leaving participant 6 out
(1) Confusion matrix:
 [[ 6  0  0]
 [ 0 15  0]
 [ 0  1  8]]
(2) micro F1 score = 0.97
(3) Weighted F1 score = 0.97
(4) Percentage Classification accuracy = 96.67%
--------------------------------
LEAVING PARTICIPANT 7 OUT:
The model for participant 7 has been saved
Leaving participant 7 out
(1) Confusion matrix:
 [[ 5  0  0]
 [ 0 16  0]
 [ 1  1  7]]
(2) micro F1 score = 0.93
(3) Weighted F1 score = 0.93
(4) Percentage Classification accuracy = 93.33%
--------------------------------
LEAVING PARTICIPANT 8 OUT:
The model for participant 8 has been saved
Leaving participant 8 out
(1) Confusion matrix:
 [[ 9  0  0]
 [ 0 16  0]
 [ 0  1  4]]
(2) micro F1 score = 0.97
(3) Weighted F1 score = 0.97
(4) Percentage Classification accuracy = 96.67%
--------------------------------
LEAVING PARTICIPANT 19 OUT:
The model for participant 19 has been saved
Leaving participant 19 out
(1) Confusion matrix:
 [[ 1  4  1]
 [ 0 16  0]
 [ 0  0  8]]
(2) micro F1 score = 0.83
(3) Weighted F1 score = 0.78
(4) Percentage Classification accuracy = 83.33%
--------------------------------
LEAVING PARTICIPANT 21 OUT:
The model for participant 21 has been saved
Leaving participant 21 out
(1) Confusion matrix:
 [[ 8  1  0]
 [ 0 17  0]
 [ 0  1  3]]
(2) micro F1 score = 0.93
(3) Weighted F1 score = 0.93
(4) Percentage Classification accuracy = 93.33%
--------------------------------
LEAVING PARTICIPANT 22 OUT:
The model for participant 22 has been saved
Leaving participant 22 out
(1) Confusion matrix:
 [[ 1  0  2]
 [ 1  2  2]
 [ 0  0 22]]
(2) micro F1 score = 0.83
(3) Weighted F1 score = 0.81
(4) Percentage Classification accuracy = 83.33%
--------------------------------
LEAVING PARTICIPANT 23 OUT:
The model for participant 23 has been saved
Leaving participant 23 out
(1) Confusion matrix:
 [[ 1  1  2]
 [ 0 14  0]
 [ 0  0 12]]
(2) micro F1 score = 0.9
(3) Weighted F1 score = 0.87
(4) Percentage Classification accuracy = 90.0%
--------------------------------
LEAVING PARTICIPANT 24 OUT:
The model for participant 24 has been saved
Leaving participant 24 out
(1) Confusion matrix:
 [[ 0  1  2]
 [ 0 19  0]
 [ 0  0  8]]
(2) micro F1 score = 0.9
(3) Weighted F1 score = 0.85
(4) Percentage Classification accuracy = 90.0%
--------------------------------
LEAVING PARTICIPANT 25 OUT:
The model for participant 25 has been saved
Leaving participant 25 out
(1) Confusion matrix:
 [[ 4  2  0]
 [ 0 17  0]
 [ 0  0  7]]
(2) micro F1 score = 0.93
(3) Weighted F1 score = 0.93
(4) Percentage Classification accuracy = 93.33%
--------------------------------
Using Leave One Participant Out CV (LOPOCV):
(1) Confusion matrix:
 [[130  56  14]
 [ 20 404   4]
 [ 22  30 160]]
(2) Average micro F1 score = 0.83
(3) Average weighted F1 score = 0.8
(4) Average Percentage Classification accuracy = 82.62%

Model 4 - LSTM + fully connected layers using only the emg data (48 features)¶

complete_emg = normalised_df.iloc[:,:59] hand0_emg = normalised_df.iloc[:,35:59] hand0_emg.head()

In [122]:
#hand0_emg = normalised_df.iloc[:,19:27]
hand1_emg = normalised_df.iloc[:,35:59]

emg_0 = normalised_df.iloc[:,:35]
emg_1 = pd.concat([df_info, hand1_emg], axis=1)

Create the model¶

In [123]:
class LSTM_emg_features_properties(nn.Module):
    def __init__(self):
        super().__init__()
        self.rnn = nn.LSTM(24, 15, 1, batch_first=True)
        self.fc1 = nn.Linear(3 * 15 * 2, 25)
        self.fc2 = nn.Linear(25, 10)
        self.fc3 = nn.Linear(10, 5)
          
    def forward(self, x1, x2): #, x2
        x1, (hn, cn) = self.rnn(x1) #, (self.h0, self.c0)
        x1 = F.tanh(x1)
        x2, (hm, cm) = self.rnn(x2) # (self.h0, self.c0)
        x2 = F.tanh(x2)
        
        x = torch.cat((x1, x2), 2)
        
        x = torch.flatten(x, 1) # flatten all dimensions except batch
        x = F.tanh(self.fc1(x))
        x = F.tanh(self.fc2(x))
        x = F.softmax(self.fc3(x), dim=1)
        return x
    
class LSTM_emg_features_ratings(nn.Module):
    def __init__(self):
        super().__init__()
        self.rnn = nn.LSTM(24+5, 15, 1, batch_first=True)
        self.fc1 = nn.Linear(3 * 15 * 2, 25)
        self.fc2 = nn.Linear(25, 10)
        self.fc3 = nn.Linear(10, 3)
          
    def forward(self, x1, x2): #, x2
        x1, (hn, cn) = self.rnn(x1) #, (self.h0, self.c0)
        x1 = F.tanh(x1)
        x2, (hm, cm) = self.rnn(x2) # (self.h0, self.c0)
        x2 = F.tanh(x2)
        
        x = torch.cat((x1, x2), 2)
        
        x = torch.flatten(x, 1) # flatten all dimensions except batch
        x = F.tanh(self.fc1(x))
        x = F.tanh(self.fc2(x))
        x = F.softmax(self.fc3(x), dim=1)
        return x

Run the model¶

In [124]:
LSTM_LOP0CV(emg_0, emg_1, model=LSTM_emg_features_properties(), num_folds=5, predicting_feature='property_id', learning_rate=0.005, num_epochs=70, random_state=num) #, num_inner_folds=5
LEAVING PARTICIPANT 1 OUT:
The model for participant 1 has been saved
Leaving participant 1 out
(1) Confusion matrix:
 [[2 0 4 0 0]
 [0 0 4 0 2]
 [5 0 1 0 0]
 [0 1 3 0 2]
 [1 0 2 0 3]]
(2) micro F1 score = 0.2
(3) Macro F1 score = 0.17
(4) Percentage Classification accuracy = 20.0%
--------------------------------
LEAVING PARTICIPANT 2 OUT:
The model for participant 2 has been saved
Leaving participant 2 out
(1) Confusion matrix:
 [[0 1 0 0 5]
 [0 3 0 0 3]
 [0 4 2 0 0]
 [0 2 0 3 1]
 [0 1 1 0 4]]
(2) micro F1 score = 0.4
(3) Macro F1 score = 0.38
(4) Percentage Classification accuracy = 40.0%
--------------------------------
LEAVING PARTICIPANT 3 OUT:
The model for participant 3 has been saved
Leaving participant 3 out
(1) Confusion matrix:
 [[5 0 1 0 0]
 [0 6 0 0 0]
 [0 0 6 0 0]
 [0 0 0 6 0]
 [0 0 0 0 6]]
(2) micro F1 score = 0.97
(3) Macro F1 score = 0.97
(4) Percentage Classification accuracy = 96.67%
--------------------------------
LEAVING PARTICIPANT 4 OUT:
The model for participant 4 has been saved
Leaving participant 4 out
(1) Confusion matrix:
 [[5 0 1 0 0]
 [0 5 0 1 0]
 [0 0 6 0 0]
 [0 0 0 6 0]
 [0 0 0 1 5]]
(2) micro F1 score = 0.9
(3) Macro F1 score = 0.9
(4) Percentage Classification accuracy = 90.0%
--------------------------------
LEAVING PARTICIPANT 5 OUT:
The model for participant 5 has been saved
Leaving participant 5 out
(1) Confusion matrix:
 [[4 1 0 0 1]
 [0 6 0 0 0]
 [0 0 5 0 1]
 [0 0 0 6 0]
 [0 0 0 0 6]]
(2) micro F1 score = 0.9
(3) Macro F1 score = 0.9
(4) Percentage Classification accuracy = 90.0%
--------------------------------
LEAVING PARTICIPANT 6 OUT:
The model for participant 6 has been saved
Leaving participant 6 out
(1) Confusion matrix:
 [[5 0 0 1 0]
 [0 5 0 0 1]
 [0 2 4 0 0]
 [0 0 0 6 0]
 [0 0 0 0 6]]
(2) micro F1 score = 0.87
(3) Macro F1 score = 0.86
(4) Percentage Classification accuracy = 86.67%
--------------------------------
LEAVING PARTICIPANT 7 OUT:
The model for participant 7 has been saved
Leaving participant 7 out
(1) Confusion matrix:
 [[6 0 0 0 0]
 [0 5 1 0 0]
 [0 1 4 0 1]
 [0 0 0 6 0]
 [0 0 0 2 4]]
(2) micro F1 score = 0.83
(3) Macro F1 score = 0.83
(4) Percentage Classification accuracy = 83.33%
--------------------------------
LEAVING PARTICIPANT 8 OUT:
The model for participant 8 has been saved
Leaving participant 8 out
(1) Confusion matrix:
 [[6 0 0 0 0]
 [0 6 0 0 0]
 [0 0 6 0 0]
 [0 2 0 3 1]
 [0 0 0 0 6]]
(2) micro F1 score = 0.9
(3) Macro F1 score = 0.89
(4) Percentage Classification accuracy = 90.0%
--------------------------------
LEAVING PARTICIPANT 19 OUT:
The model for participant 19 has been saved
Leaving participant 19 out
(1) Confusion matrix:
 [[6 0 0 0 0]
 [0 6 0 0 0]
 [0 0 6 0 0]
 [0 0 0 6 0]
 [1 0 0 0 5]]
(2) micro F1 score = 0.97
(3) Macro F1 score = 0.97
(4) Percentage Classification accuracy = 96.67%
--------------------------------
LEAVING PARTICIPANT 21 OUT:
The model for participant 21 has been saved
Leaving participant 21 out
(1) Confusion matrix:
 [[6 0 0 0 0]
 [0 6 0 0 0]
 [0 0 6 0 0]
 [0 0 0 6 0]
 [0 0 0 0 6]]
(2) micro F1 score = 1.0
(3) Macro F1 score = 1.0
(4) Percentage Classification accuracy = 100.0%
--------------------------------
LEAVING PARTICIPANT 22 OUT:
The model for participant 22 has been saved
Leaving participant 22 out
(1) Confusion matrix:
 [[5 1 0 0 0]
 [0 6 0 0 0]
 [1 0 5 0 0]
 [0 0 2 3 1]
 [1 0 0 1 4]]
(2) micro F1 score = 0.77
(3) Macro F1 score = 0.76
(4) Percentage Classification accuracy = 76.67%
--------------------------------
LEAVING PARTICIPANT 23 OUT:
The model for participant 23 has been saved
Leaving participant 23 out
(1) Confusion matrix:
 [[6 0 0 0 0]
 [1 5 0 0 0]
 [1 0 3 2 0]
 [0 0 0 6 0]
 [0 2 0 2 2]]
(2) micro F1 score = 0.73
(3) Macro F1 score = 0.71
(4) Percentage Classification accuracy = 73.33%
--------------------------------
LEAVING PARTICIPANT 24 OUT:
The model for participant 24 has been saved
Leaving participant 24 out
(1) Confusion matrix:
 [[5 0 0 1 0]
 [0 5 0 0 1]
 [0 0 5 1 0]
 [0 0 0 6 0]
 [1 0 0 0 5]]
(2) micro F1 score = 0.87
(3) Macro F1 score = 0.87
(4) Percentage Classification accuracy = 86.67%
--------------------------------
LEAVING PARTICIPANT 25 OUT:
The model for participant 25 has been saved
Leaving participant 25 out
(1) Confusion matrix:
 [[6 0 0 0 0]
 [0 6 0 0 0]
 [0 0 6 0 0]
 [0 0 0 6 0]
 [0 2 1 0 3]]
(2) micro F1 score = 0.9
(3) Macro F1 score = 0.89
(4) Percentage Classification accuracy = 90.0%
--------------------------------
Using Leave One Participant Out CV (LOPOCV):
(1) Confusion matrix:
 [[134   6  12   4  12]
 [  2 140  10   2  14]
 [ 14  14 130   6   4]
 [  0  10  10 138  10]
 [  8  10   8  12 130]]
(2) Average micro F1 score = 0.8
(3) Average macro F1 score = 0.79
(4) Average Percentage Classification accuracy = 80.0%

Run the model for ratings¶

In [125]:
LSTM_LOP0CV(emg_0, emg_1, model=LSTM_emg_features_ratings(), num_folds=5, predicting_feature='rating_level_num', learning_rate=0.005, num_epochs=70, random_state=num) #, num_inner_folds=5
LEAVING PARTICIPANT 1 OUT:
The model for participant 1 has been saved
Leaving participant 1 out
(1) Confusion matrix:
 [[6 1 3]
 [7 1 7]
 [1 2 2]]
(2) micro F1 score = 0.3
(3) Weighted F1 score = 0.26
(4) Percentage Classification accuracy = 30.0%
--------------------------------
LEAVING PARTICIPANT 2 OUT:
The model for participant 2 has been saved
Leaving participant 2 out
(1) Confusion matrix:
 [[ 0 13  0]
 [ 0 17  0]
 [ 0  0  0]]
(2) micro F1 score = 0.57
(3) Weighted F1 score = 0.41
(4) Percentage Classification accuracy = 56.67%
--------------------------------
LEAVING PARTICIPANT 3 OUT:
The model for participant 3 has been saved
Leaving participant 3 out
(1) Confusion matrix:
 [[10  2  0]
 [ 0 13  0]
 [ 0  0  5]]
(2) micro F1 score = 0.93
(3) Weighted F1 score = 0.93
(4) Percentage Classification accuracy = 93.33%
--------------------------------
LEAVING PARTICIPANT 4 OUT:
The model for participant 4 has been saved
Leaving participant 4 out
(1) Confusion matrix:
 [[ 8  0  0]
 [ 0 19  0]
 [ 0  2  1]]
(2) micro F1 score = 0.93
(3) Weighted F1 score = 0.92
(4) Percentage Classification accuracy = 93.33%
--------------------------------
LEAVING PARTICIPANT 5 OUT:
The model for participant 5 has been saved
Leaving participant 5 out
(1) Confusion matrix:
 [[ 4  2  0]
 [ 0 15  0]
 [ 0  9  0]]
(2) micro F1 score = 0.63
(3) Weighted F1 score = 0.53
(4) Percentage Classification accuracy = 63.33%
--------------------------------
LEAVING PARTICIPANT 6 OUT:
The model for participant 6 has been saved
Leaving participant 6 out
(1) Confusion matrix:
 [[ 6  0  0]
 [ 1 14  0]
 [ 1  3  5]]
(2) micro F1 score = 0.83
(3) Weighted F1 score = 0.82
(4) Percentage Classification accuracy = 83.33%
--------------------------------
LEAVING PARTICIPANT 7 OUT:
The model for participant 7 has been saved
Leaving participant 7 out
(1) Confusion matrix:
 [[ 5  0  0]
 [ 0 14  2]
 [ 0  3  6]]
(2) micro F1 score = 0.83
(3) Weighted F1 score = 0.83
(4) Percentage Classification accuracy = 83.33%
--------------------------------
LEAVING PARTICIPANT 8 OUT:
The model for participant 8 has been saved
Leaving participant 8 out
(1) Confusion matrix:
 [[ 4  5  0]
 [ 0 16  0]
 [ 0  2  3]]
(2) micro F1 score = 0.77
(3) Weighted F1 score = 0.75
(4) Percentage Classification accuracy = 76.67%
--------------------------------
LEAVING PARTICIPANT 19 OUT:
The model for participant 19 has been saved
Leaving participant 19 out
(1) Confusion matrix:
 [[ 2  3  1]
 [ 0 16  0]
 [ 0  0  8]]
(2) micro F1 score = 0.87
(3) Weighted F1 score = 0.84
(4) Percentage Classification accuracy = 86.67%
--------------------------------
LEAVING PARTICIPANT 21 OUT:
The model for participant 21 has been saved
Leaving participant 21 out
(1) Confusion matrix:
 [[ 9  0  0]
 [ 0 17  0]
 [ 0  1  3]]
(2) micro F1 score = 0.97
(3) Weighted F1 score = 0.96
(4) Percentage Classification accuracy = 96.67%
--------------------------------
LEAVING PARTICIPANT 22 OUT:
The model for participant 22 has been saved
Leaving participant 22 out
(1) Confusion matrix:
 [[ 1  0  2]
 [ 0  2  3]
 [ 0  0 22]]
(2) micro F1 score = 0.83
(3) Weighted F1 score = 0.8
(4) Percentage Classification accuracy = 83.33%
--------------------------------
LEAVING PARTICIPANT 23 OUT:
The model for participant 23 has been saved
Leaving participant 23 out
(1) Confusion matrix:
 [[ 4  0  0]
 [ 0 12  2]
 [ 0  0 12]]
(2) micro F1 score = 0.93
(3) Weighted F1 score = 0.93
(4) Percentage Classification accuracy = 93.33%
--------------------------------
LEAVING PARTICIPANT 24 OUT:
The model for participant 24 has been saved
Leaving participant 24 out
(1) Confusion matrix:
 [[ 1  1  1]
 [ 0 19  0]
 [ 0  1  7]]
(2) micro F1 score = 0.9
(3) Weighted F1 score = 0.88
(4) Percentage Classification accuracy = 90.0%
--------------------------------
LEAVING PARTICIPANT 25 OUT:
The model for participant 25 has been saved
Leaving participant 25 out
(1) Confusion matrix:
 [[ 5  1  0]
 [ 0 17  0]
 [ 0  1  6]]
(2) micro F1 score = 0.93
(3) Weighted F1 score = 0.93
(4) Percentage Classification accuracy = 93.33%
--------------------------------
Using Leave One Participant Out CV (LOPOCV):
(1) Confusion matrix:
 [[130  56  14]
 [ 16 384  28]
 [  4  48 160]]
(2) Average micro F1 score = 0.8
(3) Average weighted F1 score = 0.77
(4) Average Percentage Classification accuracy = 80.24%
In [ ]:
dtryftugyihuoi
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
def find_best_model_for_fold_4(train_dataloader, val_dataloader, learning_rate, num_epochs):

    # Model
    train_model = LSTM_2()

    # Loss and Optimiser
    criterion = torch.nn.CrossEntropyLoss()
    optimizer = optim.SGD(train_model.parameters(), lr=learning_rate, momentum=0.7)

    best_avg_loss = np.inf
    best_model = None
    #best_model_epoch_num = np.inf
    train_loss_lst = []
    val_loss_lst = []
    avg_loss_lst = []

    for epoch in range(num_epochs):  # loop over the dataset multiple times

        #Set the model in training mode
        train_model.train()

        # Initialise the total training and validation loss
        epoch_train_loss = 0
        epoch_val_loss = 0
        avg_loss = 0
        #count_train = 0
        #count_val = 0

        #running_loss = 0.0
        for i, train_data in enumerate(train_dataloader, 0):
            #print(len(train_data))
            #count_train += 1
            # get the inputs; data is a list of [input1, input2, label]
            train_input1, train_input2, train_labels = train_data #train_input2, 

            #train_labels = train_labels.type(torch.LongTensor)

            # zero the parameter gradients
            optimizer.zero_grad()

            # forward + backward + optimize
            train_preds = train_model(train_input1, train_input2)  
            #print(train_labels)#

            train_loss = criterion(train_preds, train_labels)
            train_loss.backward()
            optimizer.step()

            # Update training loss
            epoch_train_loss += train_loss.item()

        # Switch off auto grad for evaluation
        with torch.no_grad():

            # Set the model in evaluation mode
            train_model.eval()

            for j, val_data in enumerate(val_dataloader, 0):
               # count_val += 1
               # print(len(val_data))
            # get the inputs; data is a list of [input1, input2, label]
                val_input1, val_input2, val_labels = val_data # val_input2, 

                #val_labels = val_labels.type(torch.LongTensor)

                val_preds = train_model(val_input1, val_input2) #, val_input2

                # Update validation loss
                val_loss = criterion(val_preds, val_labels)

                epoch_val_loss += val_loss.item()
        #print(len(train_dataloader), len(val_dataloader))       
        avg_training_loss = epoch_train_loss / len(train_dataloader) #count_train
        avg_validation_loss = epoch_val_loss / len(val_dataloader) #count_val
        avg_loss = (avg_training_loss + avg_validation_loss) / 2
        
        train_loss_lst.append(avg_training_loss)
        val_loss_lst.append(avg_validation_loss)
        avg_loss_lst.append(avg_loss)
         
        #print(f'epoch {epoch+1}: train loss = {round(avg_training_loss,2)}, val loss = {round(avg_validation_loss,2)}, average loss = {round(avg_loss,2)}')

        if avg_loss < best_avg_loss:
            best_avg_loss = avg_loss
            best_model = train_model.state_dict()

    return best_avg_loss, best_model, train_loss_lst, val_loss_lst, avg_loss_lst   #, avg_loss_lst, 
In [ ]:
# Original
def LSTM_LOP0CV_properties_2(data_0, data_1, num_folds=5, predicting_feature='property_id', learning_rate=0.01, num_epochs=10, random_state=num): #, num_inner_folds=5
    # Set fixed random number seed
    torch.manual_seed(num)
    
   # elif predicting_feature == 'rating_level_num':
    #weighted_f1_lst = [] 
    total_conf_mat = 0
    micro_f1_lst = []
    macro_f1_lst = []
    acc_lst = []

    #lst = [6,24,2]#,24]
    
    for participant in sorted(data_0.participant_id.unique()): # #:lst: #
        print(f'LEAVING PARTICIPANT {participant} OUT:')
        
        # Split the data into training and testing
        training_data_0 = data_0[data_0.participant_id != participant] 
        training_data_1 = data_1[data_1.participant_id != participant] 
        testing_data_0 = data_0[data_0.participant_id == participant] 
        testing_data_1 = data_1[data_1.participant_id == participant] 

        # Data preparation
        X_train_0 = create_X_3d(training_data_0, 11)
        X_train_1 = create_X_3d(training_data_1, 11)        
        y_train = create_y_train_for_3d_X(training_data_0, predicting_feature = 'property_id')
        X_test_0 = create_X_3d(testing_data_0, 11) 
        X_test_1 = create_X_3d(testing_data_1, 11)
        y_test = create_y_test_for_3d_X(testing_data_0, predicting_feature = 'property_id')
        #print(y_test)

        #print(X_train_0.shape)
        #print(X_train_1.shape)
        #print(y_train.shape)
        #print(X_test_0.shape)
        #print(X_test_1.shape)
        #print(y_test.shape)
 
        # Create the datasets and dataloaders
        train_dataset = TensorDataset(X_train_0, X_train_1, y_train) 
        
        test_dataset = TensorDataset(X_test_0, X_test_1, y_test)
        test_dataloader = torch.utils.data.DataLoader(test_dataset, shuffle=True, batch_size=30) # num_workers=2,       
            
        # Configure the cross-validation procedure
        cv_inner = KFold(n_splits=num_folds, shuffle=True, random_state=num)
                
        min_avg_loss_subject = np.inf
        best_model_subject = None
        
        best_train_loss_lst = None
        best_val_loss_lst = None
        best_avg_loss_lst = None
        best_fold = np.inf

        for fold, (train_ids, val_ids) in enumerate(cv_inner.split(train_dataset)):
            #print(f'FOLD {fold+1}:')
                       
            # Sample elements randomly from a given list of ids, no replacement.
            train_subsampler = torch.utils.data.SubsetRandomSampler(train_ids) # The ids are the same for both
            val_subsampler = torch.utils.data.SubsetRandomSampler(val_ids)

            # Define data loaders for training and testing data in this fold
            train_dataloader = torch.utils.data.DataLoader(train_dataset, sampler=train_subsampler) #, batch_size=100
            val_dataloader = torch.utils.data.DataLoader(train_dataset, sampler=val_subsampler) #, batch_size=20        

            avg_loss_fold, best_model_fold, fold_train_loss_lst, fold_val_loss_lst, fold_avg_loss_lst = find_best_model_for_fold_4(train_dataloader, val_dataloader, learning_rate, num_epochs)
                           
            if avg_loss_fold < min_avg_loss_subject:
                min_avg_loss_subject = avg_loss_fold
                best_model_subject = best_model_fold
                best_train_loss_lst = fold_train_loss_lst
                best_val_loss_lst = fold_val_loss_lst
                best_avg_loss_lst = fold_avg_loss_lst
                best_fold = fold+1

        fig = plt.figure(f"{participant}")                  
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_train_loss_lst)
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_val_loss_lst)
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_avg_loss_lst)
        plt.title(f"Loss when participant {participant} is left out for fold {best_fold} (lr={learning_rate}, num_epochs ={num_epochs})")
        plt.legend(['train loss', 'val loss', 'avg_loss'])

        # save trained model 
        name = 'model_participant_'+str(participant)+'.pt'
        torch.save(best_model_subject, name)
        print(f'The model for participant {participant} has been saved')
        
        test_model = LSTM_2()
        test_model.load_state_dict(torch.load(name))

        dataiter = iter(test_dataloader) 
        test_input1, test_input2, test_labels = dataiter.next() 
    
        test_preds = test_model(test_input1, test_input2) 
        
        test_preds_np = test_preds.detach().numpy()
        test_predicted_np = np.argmax(test_preds_np, axis = 1)
        
        test_labels_np = test_labels.numpy()       
        

        conf_mat = confusion_matrix(test_labels_np, test_predicted_np, labels=[0, 1, 2, 3, 4])
        macro_f1_score = f1_score(test_labels_np, test_predicted_np, average='macro') 
        micro_f1_score = f1_score(test_labels_np, test_predicted_np, average='micro')  
        acc = accuracy_score(test_labels_np, test_predicted_np)

        print(f"Leaving participant {participant} out")
        print("(1) Confusion matrix:\n", conf_mat)
        print(f"(2) micro F1 score = {round(micro_f1_score,2)}")
        print(f"(3) macro F1 score = {round(macro_f1_score,2)}")    
        print(f"(4) Percentage Classification accuracy = {round(acc*100,2)}%")
        
        total_conf_mat += conf_mat 
        micro_f1_lst.append(micro_f1_score)
        macro_f1_lst.append(macro_f1_score) 
        acc_lst.append(acc)
        print('--------------------------------')
        
    avg_micro_f1_score = sum(micro_f1_lst) / len(micro_f1_lst)
    avg_macro_f1_score = sum(macro_f1_lst) / len(macro_f1_lst)         
    avg_acc = sum(acc_lst) / len(acc_lst)   
    
    print(f'Using Leave One Participant Out CV (LOPOCV):') 
    print("(1) Confusion matrix:\n", total_conf_mat)
    print(f"(2) Average micro F1 score = {round(avg_micro_f1_score,2)}")
    #if predicting_feature == 'property_id':
    print(f"(3) Average macro F1 score = {round(avg_macro_f1_score,2)}")
    #elif predicting_feature == 'rating_level_num':
        #print(f"(3) Average weighted F1 score = {round(avg_weighted_f1_score,2)}")      
    print(f"(4) Average Percentage Classification accuracy = {round(avg_acc*100,2)}%")
            
In [ ]:
LSTM_LOP0CV_properties_2(emg_0, emg_1, num_folds=5, predicting_feature='property_id', learning_rate=0.05, num_epochs=70, random_state=num) 
In [ ]:
t2 = time.time()

Model 5 - CNN + LSTM¶

In [ ]:
complete_emg = normalised_df.iloc[:,:59]
hand0_emg = normalised_df.iloc[:,43:51]
hand0_emg.head()
In [ ]:
hand0_emg = normalised_df.iloc[:,19:27]
hand1_emg = normalised_df.iloc[:,43:51]

emg_0 = pd.concat([df_info, hand0_emg], axis=1)
emg_1 = pd.concat([df_info, hand1_emg], axis=1)

Create the model¶

In [ ]:
class CNN_LSTM(nn.Module):
    def __init__(self):
        super().__init__()
        
        self.conv1 = nn.Conv1d(in_channels=3, out_channels=3, kernel_size=1, stride=1, padding=0, groups=3) # Change kernel size to 3
        self.pool = nn.MaxPool1d(1, 1) # Change kernel size to 1 and stride to 1
        self.rnn = nn.LSTM(8, 4, 1, batch_first=True)
        #self.h0 = torch.randn(1, 50, 7)
        #self.c0 = torch.randn(1, 50, 7)
        self.fc1 = nn.Linear(3 * 4 * 2, 18)
        self.fc2 = nn.Linear(18, 10)
        self.fc3 = nn.Linear(10, 5)
          
    def forward(self, x1, x2): #, x2
        x1 = self.pool(F.tanh(self.conv1(x1))) # Use tanh instead?
        x2 = self.pool(F.tanh(self.conv1(x2))) # Use tanh instead?
        
        #x = self.pool(F.relu(self.conv2(x)))
        x1, (hn, cn) = self.rnn(x1) #, (self.h0, self.c0)
        x1 = F.tanh(x1)
        x2, (hm, cm) = self.rnn(x2) # (self.h0, self.c0)
        x2 = F.tanh(x2)
        
        x = torch.cat((x1, x2), 2)
        
        x = torch.flatten(x, 1) # flatten all dimensions except batch
        x = F.tanh(self.fc1(x))
        x = F.tanh(self.fc2(x))
        x = F.softmax(self.fc3(x), dim=1)
        return x
In [ ]:
m3 = CNN_LSTM()
print(m3)
In [ ]:
def find_best_model_for_fold_3(train_dataloader, val_dataloader, learning_rate, num_epochs):

    # Model
    train_model = CNN_LSTM()

    # Loss and Optimiser
    criterion = torch.nn.CrossEntropyLoss()
    optimizer = optim.SGD(train_model.parameters(), lr=learning_rate, momentum=0.7)

    best_avg_loss = np.inf
    best_model = None
    #best_model_epoch_num = np.inf
    train_loss_lst = []
    val_loss_lst = []
    avg_loss_lst = []

    for epoch in range(num_epochs):  # loop over the dataset multiple times

        #Set the model in training mode
        train_model.train()

        # Initialise the total training and validation loss
        epoch_train_loss = 0
        epoch_val_loss = 0
        avg_loss = 0
        #count_train = 0
        #count_val = 0

        #running_loss = 0.0
        for i, train_data in enumerate(train_dataloader, 0):
            #print(len(train_data))
            #count_train += 1
            # get the inputs; data is a list of [input1, input2, label]
            train_input1, train_input2, train_labels = train_data #train_input2, 

            #train_labels = train_labels.type(torch.LongTensor)

            # zero the parameter gradients
            optimizer.zero_grad()

            # forward + backward + optimize
            train_preds = train_model(train_input1, train_input2)  
            #print(train_labels)#

            train_loss = criterion(train_preds, train_labels)
            train_loss.backward()
            optimizer.step()

            # Update training loss
            epoch_train_loss += train_loss.item()

        # Switch off auto grad for evaluation
        with torch.no_grad():

            # Set the model in evaluation mode
            train_model.eval()

            for j, val_data in enumerate(val_dataloader, 0):
               # count_val += 1
               # print(len(val_data))
            # get the inputs; data is a list of [input1, input2, label]
                val_input1, val_input2, val_labels = val_data # val_input2, 

                #val_labels = val_labels.type(torch.LongTensor)

                val_preds = train_model(val_input1, val_input2) #, val_input2

                # Update validation loss
                val_loss = criterion(val_preds, val_labels)

                epoch_val_loss += val_loss.item()
        #print(len(train_dataloader), len(val_dataloader))       
        avg_training_loss = epoch_train_loss / len(train_dataloader) #count_train
        avg_validation_loss = epoch_val_loss / len(val_dataloader) #count_val
        avg_loss = (avg_training_loss + avg_validation_loss) / 2
        
        train_loss_lst.append(avg_training_loss)
        val_loss_lst.append(avg_validation_loss)
        avg_loss_lst.append(avg_loss)
         
        print(f'epoch {epoch+1}: train loss = {round(avg_training_loss,2)}, val loss = {round(avg_validation_loss,2)}, average loss = {round(avg_loss,2)}')

        if avg_loss < best_avg_loss:
            best_avg_loss = avg_loss
            best_model = train_model.state_dict()

    return best_avg_loss, best_model, train_loss_lst, val_loss_lst, avg_loss_lst   #, avg_loss_lst, 
In [ ]:
# Original
def CNN_LSTM_LOP0CV_properties_1(data_0, data_1, num_folds=5, predicting_feature='property_id', learning_rate=0.01, num_epochs=10, random_state=num): #, num_inner_folds=5
    # Set fixed random number seed
    torch.manual_seed(num)
    
   # elif predicting_feature == 'rating_level_num':
    #weighted_f1_lst = [] 
    total_conf_mat = 0
    micro_f1_lst = []
    macro_f1_lst = []
    acc_lst = []

    lst = [6,24,2]#,24]
    
    for participant in lst: #sorted(data0.participant_id.unique()): # #:lst: #
        print(f'LEAVING PARTICIPANT {participant} OUT:')
        
        # Split the data into training and testing
        training_data_0 = data_0[data_0.participant_id != participant] 
        training_data_1 = data_1[data_1.participant_id != participant] 
        testing_data_0 = data_0[data_0.participant_id == participant] 
        testing_data_1 = data_1[data_1.participant_id == participant] 

        # Data preparation
        X_train_0 = create_X_3d(training_data_0, 11)
        X_train_1 = create_X_3d(training_data_1, 11)        
        y_train = create_y_train_for_3d_X(training_data_0, predicting_feature = 'property_id')
        X_test_0 = create_X_3d(testing_data_0, 11) 
        X_test_1 = create_X_3d(testing_data_1, 11)
        y_test = create_y_test_for_3d_X(testing_data_0, predicting_feature = 'property_id')
        #print(y_test)

        #print(X_train_0.shape)
        #print(X_train_1.shape)
        #print(y_train.shape)
        #print(X_test_0.shape)
        #print(X_test_1.shape)
        #print(y_test.shape)
 
        # Create the datasets and dataloaders
        train_dataset = TensorDataset(X_train_0, X_train_1, y_train) 
        
        test_dataset = TensorDataset(X_test_0, X_test_1, y_test)
        test_dataloader = torch.utils.data.DataLoader(test_dataset, shuffle=True, batch_size=30) # num_workers=2,       
            
        # Configure the cross-validation procedure
        cv_inner = KFold(n_splits=num_folds, shuffle=True, random_state=num)
                
        min_avg_loss_subject = np.inf
        best_model_subject = None
        
        best_train_loss_lst = None
        best_val_loss_lst = None
        best_avg_loss_lst = None
        best_fold = np.inf

        for fold, (train_ids, val_ids) in enumerate(cv_inner.split(train_dataset)):
            #print(f'FOLD {fold+1}:')
                       
            # Sample elements randomly from a given list of ids, no replacement.
            train_subsampler = torch.utils.data.SubsetRandomSampler(train_ids) # The ids are the same for both
            val_subsampler = torch.utils.data.SubsetRandomSampler(val_ids)

            # Define data loaders for training and testing data in this fold
            train_dataloader = torch.utils.data.DataLoader(train_dataset, sampler=train_subsampler) #, batch_size=100
            val_dataloader = torch.utils.data.DataLoader(train_dataset, sampler=val_subsampler) #, batch_size=20        

            avg_loss_fold, best_model_fold, fold_train_loss_lst, fold_val_loss_lst, fold_avg_loss_lst = find_best_model_for_fold_3(train_dataloader, val_dataloader, learning_rate, num_epochs)
                           
            if avg_loss_fold < min_avg_loss_subject:
                min_avg_loss_subject = avg_loss_fold
                best_model_subject = best_model_fold
                best_train_loss_lst = fold_train_loss_lst
                best_val_loss_lst = fold_val_loss_lst
                best_avg_loss_lst = fold_avg_loss_lst
                best_fold = fold+1

        fig = plt.figure(f"{participant}")                  
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_train_loss_lst)
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_val_loss_lst)
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_avg_loss_lst)
        plt.title(f"Loss when participant {participant} is left out for fold {best_fold} (lr={learning_rate}, num_epochs ={num_epochs})")
        plt.legend(['train loss', 'val loss', 'avg_loss'])

        # save trained model 
        name = 'model_participant_'+str(participant)+'.pt'
        torch.save(best_model_subject, name)
        print(f'The model for participant {participant} has been saved')
        
        test_model = CNN_LSTM()
        test_model.load_state_dict(torch.load(name))

        dataiter = iter(test_dataloader) 
        test_input1, test_input2, test_labels = dataiter.next() 
    
        test_preds = test_model(test_input1, test_input2) 
        
        test_preds_np = test_preds.detach().numpy()
        test_predicted_np = np.argmax(test_preds_np, axis = 1)
        
        test_labels_np = test_labels.numpy()       
        

        conf_mat = confusion_matrix(test_labels_np, test_predicted_np, labels=[0, 1, 2, 3, 4])
        macro_f1_score = f1_score(test_labels_np, test_predicted_np, average='macro') 
        micro_f1_score = f1_score(test_labels_np, test_predicted_np, average='micro')  
        acc = accuracy_score(test_labels_np, test_predicted_np)

        print(f"Leaving participant {participant} out")
        print("(1) Confusion matrix:\n", conf_mat)
        print(f"(2) micro F1 score = {round(micro_f1_score,2)}")
        print(f"(3) macro F1 score = {round(macro_f1_score,2)}")    
        print(f"(4) Percentage Classification accuracy = {round(acc*100,2)}%")
        
        total_conf_mat += conf_mat 
        micro_f1_lst.append(micro_f1_score)
        macro_f1_lst.append(macro_f1_score) 
        acc_lst.append(acc)
        print('--------------------------------')
        
    avg_micro_f1_score = sum(micro_f1_lst) / len(micro_f1_lst)
    avg_macro_f1_score = sum(macro_f1_lst) / len(macro_f1_lst)         
    avg_acc = sum(acc_lst) / len(acc_lst)   
    
    print(f'Using Leave One Participant Out CV (LOPOCV):') 
    print("(1) Confusion matrix:\n", total_conf_mat)
    print(f"(2) Average micro F1 score = {round(avg_micro_f1_score,2)}")
    #if predicting_feature == 'property_id':
    print(f"(3) Average macro F1 score = {round(avg_macro_f1_score,2)}")
    #elif predicting_feature == 'rating_level_num':
        #print(f"(3) Average weighted F1 score = {round(avg_weighted_f1_score,2)}")      
    print(f"(4) Average Percentage Classification accuracy = {round(avg_acc*100,2)}%")
            

Run the model¶

In [ ]:
CNN_LSTM_LOP0CV_properties_1(emg_0, emg_1, num_folds=5, predicting_feature='property_id', learning_rate=0.3, num_epochs=30, random_state=num) 
In [ ]:
CNN_LSTM_LOP0CV_properties_1(emg_0, emg_1, num_folds=5, predicting_feature='property_id', learning_rate=0.3, num_epochs=30, random_state=num) 
In [ ]:
t2 = time.time()
In [ ]:
def find_best_model_for_fold_2(train_dataloader, val_dataloader, learning_rate, num_epochs):

    # Model
    train_model = Linear_model_2()

    # Loss and Optimiser
    criterion = torch.nn.CrossEntropyLoss()
    optimizer = optim.SGD(train_model.parameters(), lr=learning_rate, momentum=0.7)

    best_avg_loss = np.inf
    best_model = None
    #best_model_epoch_num = np.inf
    train_loss_lst = []
    val_loss_lst = []
    avg_loss_lst = []

    for epoch in range(num_epochs):  # loop over the dataset multiple times

        #Set the model in training mode
        train_model.train()

        # Initialise the total training and validation loss
        epoch_train_loss = 0
        epoch_val_loss = 0
        avg_loss = 0
        #count_train = 0
        #count_val = 0

        #running_loss = 0.0
        for i, train_data in enumerate(train_dataloader, 0):
            #print(len(train_data))
            #count_train += 1
            # get the inputs; data is a list of [input1, input2, label]
            train_input1, train_labels = train_data #train_input2, 

            #train_labels = train_labels.type(torch.LongTensor)

            # zero the parameter gradients
            optimizer.zero_grad()

            # forward + backward + optimize
            train_preds = train_model(train_input1) #, train_input2
            #print(train_labels)#

            train_loss = criterion(train_preds, train_labels)
            train_loss.backward()
            optimizer.step()

            # Update training loss
            epoch_train_loss += train_loss.item()

        # Switch off auto grad for evaluation
        with torch.no_grad():

            # Set the model in evaluation mode
            train_model.eval()

            for j, val_data in enumerate(val_dataloader, 0):
               # count_val += 1
               # print(len(val_data))
            # get the inputs; data is a list of [input1, input2, label]
                val_input1, val_labels = val_data # val_input2, 

                #val_labels = val_labels.type(torch.LongTensor)

                val_preds = train_model(val_input1) #, val_input2

                # Update validation loss
                val_loss = criterion(val_preds, val_labels)

                epoch_val_loss += val_loss.item()
        #print(len(train_dataloader), len(val_dataloader))       
        avg_training_loss = epoch_train_loss / len(train_dataloader) #count_train
        avg_validation_loss = epoch_val_loss / len(val_dataloader) #count_val
        avg_loss = (avg_training_loss + avg_validation_loss) / 2
        
        train_loss_lst.append(avg_training_loss)
        val_loss_lst.append(avg_validation_loss)
        avg_loss_lst.append(avg_loss)
         
        #print(f'epoch {epoch+1}: train loss = {round(avg_training_loss,2)}, val loss = {round(avg_validation_loss,2)}, average loss = {round(avg_loss,2)}')

        if avg_loss < best_avg_loss:
            best_avg_loss = avg_loss
            best_model = train_model.state_dict()

    return best_avg_loss, best_model, train_loss_lst, val_loss_lst, avg_loss_lst   #, avg_loss_lst, 
In [ ]:
# Original
def Linear_LOP0CV_properties_2(data, num_folds=5, predicting_feature='property_id', learning_rate=0.01, num_epochs=10, random_state=num, X_dim=2): #, num_inner_folds=5
    # Set fixed random number seed
    torch.manual_seed(num)
    
   # elif predicting_feature == 'rating_level_num':
    #weighted_f1_lst = [] 
    total_conf_mat = 0
    micro_f1_lst = []
    macro_f1_lst = []
    acc_lst = []

    #lst = [6,24,2]#,24]
    
    for participant in sorted(data.participant_id.unique()): # #:lst: #
        print(f'LEAVING PARTICIPANT {participant} OUT:')
        
        # Split the data into training and testing
        training_data = data[data.participant_id != participant] 
        testing_data = data[data.participant_id == participant] 

        # Data preparation
        if X_dim == 2:
            X_train = create_X_2d(training_data, 11)       
            y_train = create_y_train_for_2d_X(training_data, predicting_feature = 'property_id')
            X_test = create_X_2d(testing_data, 11) 
            y_test = create_y_test_for_2d_X(testing_data, predicting_feature = 'property_id')
        elif X_dim == 3:
            X_train = create_X_3d(training_data, 11)       
            y_train = create_y_train_for_3d_X(training_data, predicting_feature = 'property_id')
            X_test = create_X_3d(testing_data, 11) 
            y_test = create_y_test_for_3d_X(testing_data, predicting_feature = 'property_id')

        #print(X_train.shape)
        #print(y_train.shape)
        #print(X_test.shape)
        #print(y_test.shape)
 
        # Create the datasets and dataloaders
        train_dataset = TensorDataset(X_train, y_train) 
        
        test_dataset = TensorDataset(X_test, y_test)
        test_dataloader = torch.utils.data.DataLoader(test_dataset, shuffle=True, batch_size=90) # num_workers=2,       
            
        # Configure the cross-validation procedure
        cv_inner = KFold(n_splits=num_folds, shuffle=True, random_state=num)
                
        min_avg_loss_subject = np.inf
        best_model_subject = None
        
        best_train_loss_lst = None
        best_val_loss_lst = None
        best_avg_loss_lst = None
        best_fold = np.inf

        for fold, (train_ids, val_ids) in enumerate(cv_inner.split(train_dataset)):
            #print(f'FOLD {fold+1}:')
                       
            # Sample elements randomly from a given list of ids, no replacement.
            train_subsampler = torch.utils.data.SubsetRandomSampler(train_ids) # The ids are the same for both
            val_subsampler = torch.utils.data.SubsetRandomSampler(val_ids)

            # Define data loaders for training and testing data in this fold
            train_dataloader = torch.utils.data.DataLoader(train_dataset, sampler=train_subsampler) #, batch_size=100
            val_dataloader = torch.utils.data.DataLoader(train_dataset, sampler=val_subsampler) #, batch_size=20        

            avg_loss_fold, best_model_fold, fold_train_loss_lst, fold_val_loss_lst, fold_avg_loss_lst = find_best_model_for_fold_2(train_dataloader, val_dataloader, learning_rate, num_epochs)
                           
            if avg_loss_fold < min_avg_loss_subject:
                min_avg_loss_subject = avg_loss_fold
                best_model_subject = best_model_fold
                best_train_loss_lst = fold_train_loss_lst
                best_val_loss_lst = fold_val_loss_lst
                best_avg_loss_lst = fold_avg_loss_lst
                best_fold = fold+1

        fig = plt.figure(f"{participant}")                  
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_train_loss_lst)
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_val_loss_lst)
        plt.plot(np.linspace(1, num_epochs, num_epochs).astype(int), best_avg_loss_lst)
        plt.title(f"Loss when participant {participant} is left out for fold {best_fold} (lr={learning_rate}, num_epochs ={num_epochs})")
        plt.legend(['train loss', 'val loss', 'avg_loss'])

        # save trained model 
        name = 'model_participant_'+str(participant)+'.pt'
        torch.save(best_model_subject, name)
        print(f'The model for participant {participant} has been saved')
        
        test_model = Linear_model_2()
        test_model.load_state_dict(torch.load(name))

        dataiter = iter(test_dataloader) 
        test_input1, test_labels = dataiter.next() 
    
        test_preds = test_model(test_input1) 
        
        test_preds_np = test_preds.detach().numpy()
        test_predicted_np = np.argmax(test_preds_np, axis = 1)
        
        test_labels_np = test_labels.numpy()       
        

        conf_mat = confusion_matrix(test_labels_np, test_predicted_np, labels=[0, 1, 2, 3, 4])
        macro_f1_score = f1_score(test_labels_np, test_predicted_np, average='macro') 
        micro_f1_score = f1_score(test_labels_np, test_predicted_np, average='micro')  
        acc = accuracy_score(test_labels_np, test_predicted_np)

        print(f"Leaving participant {participant} out")
        print("(1) Confusion matrix:\n", conf_mat)
        print(f"(2) micro F1 score = {round(micro_f1_score,2)}")
        print(f"(3) macro F1 score = {round(macro_f1_score,2)}")    
        print(f"(4) Percentage Classification accuracy = {round(acc*100,2)}%")
        
        total_conf_mat += conf_mat 
        micro_f1_lst.append(micro_f1_score)
        macro_f1_lst.append(macro_f1_score) 
        acc_lst.append(acc)
        print('--------------------------------')
        
    avg_micro_f1_score = sum(micro_f1_lst) / len(micro_f1_lst)
    avg_macro_f1_score = sum(macro_f1_lst) / len(macro_f1_lst)         
    avg_acc = sum(acc_lst) / len(acc_lst)   
    
    print(f'Using Leave One Participant Out CV (LOPOCV):') 
    print("(1) Confusion matrix:\n", total_conf_mat)
    print(f"(2) Average micro F1 score = {round(avg_micro_f1_score,2)}")
    #if predicting_feature == 'property_id':
    print(f"(3) Average macro F1 score = {round(avg_macro_f1_score,2)}")
    #elif predicting_feature == 'rating_level_num':
        #print(f"(3) Average weighted F1 score = {round(avg_weighted_f1_score,2)}")      
    print(f"(4) Average Percentage Classification accuracy = {round(avg_acc*100,2)}%")